home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / trap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  63.4 KB  |  2,660 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)trap.c    3.1    93/06/20    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. #ifdef OVLB
  8. const char *traps[TRAPNUM] = {
  9.     "",
  10.     "n arrow trap",
  11.     " dart trap",
  12.     " falling rock trap",
  13.     " squeaky board",
  14.     " bear trap",
  15.     " land mine",
  16.     " sleeping gas trap",
  17.     " rust trap",
  18.     " fire trap",
  19.     " pit",
  20.     " spiked pit",
  21.     " trapdoor",
  22.     " teleportation trap",
  23.     " level teleporter",
  24.     " magic portal",
  25.     " web",
  26.     " statue trap",
  27.     " magic trap",
  28.     "n anti-magic field"
  29. #ifdef POLYSELF
  30.     ," polymorph trap"
  31. #endif
  32. };
  33.  
  34. #endif /* OVLB */
  35.  
  36. static void FDECL(domagicportal,(struct trap *));
  37. static void NDECL(dofiretrap);
  38. static void NDECL(domagictrap);
  39. static boolean FDECL(emergency_disrobe,(boolean *));
  40. STATIC_DCL boolean FDECL(thitm, (int, struct monst *, struct obj *, int));
  41.  
  42. #ifdef OVLB
  43.  
  44. static int FDECL(teleok, (int,int,BOOLEAN_P));
  45. static void NDECL(vtele);
  46. static void FDECL(no_fall_through, (BOOLEAN_P));
  47.  
  48. /* Generic rust-armor function.  Returns TRUE if a message was printed;
  49.  * "print", if set, means to print a message (and thus to return TRUE) even
  50.  * if the item could not be rusted; otherwise a message is printed and TRUE is
  51.  * returned only for rustable items.
  52.  */
  53. boolean
  54. rust_dmg(otmp, ostr, type, print)
  55. register struct obj *otmp;
  56. register const char *ostr;
  57. int type;
  58. boolean print;
  59. {
  60.     static NEARDATA const char *action[] = { "smoulder", "rust", "rot", "corrode" };
  61.     static NEARDATA const char *msg[] =  { "burnt", "rusted", "rotten", "corroded" };
  62.     boolean vulnerable = FALSE;
  63.     boolean plural;
  64.     boolean grprot = FALSE;
  65.  
  66.     if (!otmp) return(FALSE);
  67.     switch(type) {
  68.         case 0:
  69.         case 2: vulnerable = is_flammable(otmp); break;
  70.         case 1: vulnerable = is_rustprone(otmp); grprot = TRUE; break;
  71.         case 3: vulnerable = is_corrodeable(otmp); grprot = TRUE; break;
  72.     }
  73.  
  74.     if (!print && (!vulnerable || otmp->oerodeproof || otmp->oeroded == MAX_ERODE))
  75.         return FALSE;
  76.  
  77.     plural = is_gloves(otmp) || is_boots(otmp);
  78.  
  79.     if (!vulnerable) {
  80.         if (flags.verbose)
  81.             Your("%s %s not affected.", ostr, plural ? "are" : "is");
  82.     } else if (otmp->oeroded < MAX_ERODE) {
  83.         if (grprot && otmp->greased) {
  84.             grease_protect(otmp,ostr,plural);
  85.         } else if (otmp->oerodeproof || (otmp->blessed && !rnl(4))) {
  86.             if (flags.verbose)
  87.                 pline("Somehow, your %s %s not affected.",
  88.                     ostr, plural ? "are" : "is");
  89.         } else {
  90.             Your("%s %s%s%s!", ostr, action[type],
  91.                 plural ? "" : "s",
  92.                     otmp->oeroded+1 == MAX_ERODE ? " completely" :
  93.                 otmp->oeroded ? " further" : "");
  94.             otmp->oeroded++;
  95.         }
  96.     } else {
  97.         if (flags.verbose)
  98.             Your("%s %s%s completely %s.", ostr,
  99.                  Blind ? "feel" : "look",
  100.                  plural ? "" : "s", msg[type]);
  101.     }
  102.     return(TRUE);
  103. }
  104.  
  105. void
  106. grease_protect(otmp,ostr,plu)
  107. register struct obj *otmp;
  108. register const char *ostr;
  109. register boolean plu;
  110. {
  111.     static const char txt[] = "protected by the layer of grease!";
  112.  
  113.     if (ostr)
  114.         Your("%s %s %s",ostr,plu ? "are" : "is",txt);
  115.     else
  116.         Your("%s %s",aobjnam(otmp,"are"),txt);
  117.     if (!rn2(2)) {
  118.         pline("The grease dissolves.");
  119.         otmp->greased = 0;
  120.     }
  121. }
  122.  
  123. struct trap *
  124. maketrap(x,y,typ)
  125. register int x, y, typ;
  126. {
  127.     register struct trap *ttmp;
  128.     register struct rm *lev;
  129.     register boolean oldplace;
  130.  
  131.     if ((ttmp = t_at(x,y)) != 0) {
  132.         if (ttmp->ttyp == MAGIC_PORTAL) return (struct trap *)0;
  133.         oldplace = TRUE;
  134.         if (u.utrap && (x == u.ux) && (y == u.uy) && 
  135.           ((u.utraptype == TT_BEARTRAP && typ != BEAR_TRAP) ||
  136.           (u.utraptype == TT_WEB && typ != WEB) ||
  137.           (u.utraptype == TT_PIT && typ != PIT && typ != SPIKED_PIT)))
  138.             u.utrap = 0;
  139.     } else {
  140.         oldplace = FALSE;
  141.         ttmp = newtrap();
  142.         ttmp->tx = x;
  143.         ttmp->ty = y;
  144.     }
  145.     ttmp->ttyp = typ;
  146.     switch(typ) {
  147.         case STATUE_TRAP:        /* create a "living" statue */
  148.         (void) mkcorpstat(STATUE, &mons[rndmonnum()], x, y, FALSE);
  149.         break;
  150.         case PIT:
  151.         case SPIKED_PIT:
  152.         case TRAPDOOR:
  153.         lev = &levl[x][y];
  154.         lev->doormask = 0;    /* subsumes altarmask, icedpool... */
  155.         if (IS_ROOM(lev->typ)) /* && !IS_AIR(lev->typ) */
  156.             lev->typ = ROOM;
  157. #if defined(POLYSELF) || defined(MUSE)
  158.         /*
  159.          * some cases which can happen when digging
  160.          * down while phazing thru solid areas
  161.          */
  162.         else if (lev->typ == STONE || lev->typ == SCORR)
  163.             lev->typ = CORR;
  164.         else if (IS_WALL(lev->typ) ||
  165.              IS_DOOR(lev->typ) || lev->typ == SDOOR)
  166.             lev->typ = level.flags.is_maze_lev ? ROOM :
  167.                    level.flags.is_cavernous_lev ? CORR : DOOR;
  168. #endif
  169.         unearth_objs(x, y);
  170.         break;
  171.     }
  172.     ttmp->tseen = 0;
  173.     ttmp->once = 0;
  174.     ttmp->dst.dnum = -1;
  175.     ttmp->dst.dlevel = -1;
  176.     if (!oldplace) {
  177.         ttmp->ntrap = ftrap;
  178.         ftrap = ttmp;
  179.     }
  180.     return(ttmp);
  181. }
  182.  
  183. static int
  184. teleok(x, y, trapok)
  185. register int x, y;
  186. boolean trapok;
  187. {                /* might throw him into a POOL
  188.                  * removed by GAN 10/20/86
  189.                  */
  190. #ifdef STUPID
  191.     boolean    tmp1, tmp2, tmp3, tmp4;
  192. # ifdef POLYSELF
  193.     tmp1 = isok(x,y) && (!IS_ROCK(levl[x][y].typ) ||
  194.         (passes_walls(uasmon) && may_passwall(x,y))) && !MON_AT(x, y);
  195. # else
  196.     tmp1 = isok(x,y) && !IS_ROCK(levl[x][y].typ) && !MON_AT(x, y);
  197. # endif
  198.     tmp2 = !sobj_at(BOULDER,x,y) && (trapok || !t_at(x,y));
  199.     tmp3 = !(is_pool(x,y) &&
  200.            !(Levitation || Wwalking || Amphibious
  201. # ifdef POLYSELF
  202.          || is_flyer(uasmon) || is_swimmer(uasmon)
  203.          || is_clinger(uasmon)
  204. # endif
  205.         )) && !closed_door(x,y);
  206.     tmp4 = !is_lava(x,y);
  207.     return(tmp1 && tmp2 && tmp3 && tmp4);
  208. #else
  209.     return( isok(x,y) &&
  210. # ifdef POLYSELF
  211.         (!IS_ROCK(levl[x][y].typ) ||
  212.          (passes_walls(uasmon) && may_passwall(x,y))) &&
  213. # else
  214.         !IS_ROCK(levl[x][y].typ) &&
  215. # endif
  216.         !MON_AT(x, y) &&
  217.         !sobj_at(BOULDER,x,y) && (trapok || !t_at(x,y)) &&
  218.         !(is_pool(x,y) &&
  219.         !(Levitation || Wwalking || Amphibious
  220. # ifdef POLYSELF
  221.           || is_flyer(uasmon) || is_swimmer(uasmon)
  222.           || is_clinger(uasmon)
  223. # endif
  224.           )) && !is_lava(x,y) && !closed_door(x,y));
  225. #endif
  226.     /* Note: gold is permitted (because of vaults) */
  227. }
  228.  
  229. boolean
  230. safe_teleds()
  231. {
  232.     register int nux, nuy;
  233.     short tcnt = 0;
  234.  
  235.     do {
  236.         nux = rnd(COLNO-1);
  237.         nuy = rn2(ROWNO);
  238.     } while (!teleok(nux, nuy, tcnt>200) && tcnt++ < 400);
  239.  
  240.     if (tcnt < 400) {
  241.         teleds(nux, nuy);
  242.         return TRUE;
  243.     } else
  244.         return FALSE;
  245. }
  246.  
  247. static void
  248. vtele()
  249. {
  250.     register struct mkroom *croom = search_special(VAULT);
  251.     coord c;
  252.  
  253.     if(croom && somexy(croom, &c) && teleok(c.x,c.y,FALSE)) {
  254.         teleds(c.x,c.y);
  255.         return;
  256.     }
  257.     tele();
  258. }
  259.  
  260. static void
  261. no_fall_through(td)
  262. boolean td;
  263. {
  264.     /* floor objects get a chance of falling down.  the case
  265.      * where the hero does NOT fall down is treated here.  the
  266.      * case where the hero does fall down is treated in goto_level().
  267.      * reason: the target level of the fall is not determined here,
  268.      * and it need not be the next level.  if we want falling
  269.      * objects to arrive near the player, we must call impact_drop()
  270.      * _after_ the target level is determined.
  271.      */
  272.     impact_drop((struct obj *)0, u.ux, u.uy, 0);
  273.     if (!td) {
  274.         display_nhwindow(WIN_MESSAGE, FALSE);
  275.         pline("The opening under you closes up.");
  276.     }
  277. }
  278.  
  279. void
  280. fall_through(td)
  281. boolean td;    /* td == TRUE : trapdoor */
  282. {
  283.     register int newlevel = dunlev(&u.uz);
  284.  
  285.     if(Blind && Levitation) return;
  286.  
  287.     do {
  288.         newlevel++;
  289.     } while(!rn2(4) && newlevel < dunlevs_in_dungeon(&u.uz));
  290.  
  291.     if(td) pline("A trap door opens up under you!");
  292.     else pline("The %s opens up under you!", surface(u.ux,u.uy));
  293.  
  294.     if(Levitation || u.ustuck || !Can_fall_thru(&u.uz)
  295. #ifdef POLYSELF
  296.        || is_flyer(uasmon) || is_clinger(uasmon)
  297. #endif
  298.        || (Inhell && !u.uevent.invoked &&
  299.                     newlevel == dunlevs_in_dungeon(&u.uz))
  300.         ) {
  301.             You("don't fall in.");
  302.             no_fall_through(td);
  303.             return;
  304.     }
  305. #ifdef WALKIES
  306.     if(!next_to_u()) {
  307.         You("are jerked back by your pet!");
  308.         no_fall_through(td);
  309.         return;
  310.     }
  311. #endif
  312.     if(*u.ushops) shopdig(1);
  313.     if(Is_stronghold(&u.uz)) goto_hell(TRUE, TRUE);
  314.     else {
  315.         d_level    dtmp;
  316.         dtmp.dnum = u.uz.dnum;
  317.         dtmp.dlevel = newlevel;
  318.         goto_level(&dtmp, FALSE, TRUE, FALSE);
  319.         if(!td) pline("The hole in the ceiling above you closes up.");
  320.     }
  321. }
  322.  
  323. void
  324. dotrap(trap)
  325. register struct trap *trap;
  326. {
  327.     register int ttype = trap->ttyp;
  328.     register struct monst *mtmp;
  329.     register struct obj *otmp;
  330.  
  331.     nomul(0);
  332.     if(trap->tseen && !Fumbling &&
  333. #ifdef POLYSELF
  334.        !((ttype == PIT || ttype == SPIKED_PIT) && !is_clinger(uasmon)) &&
  335. #else
  336.        !(ttype == PIT || ttype == SPIKED_PIT) &&
  337. #endif
  338.        !(ttype == MAGIC_PORTAL || ttype == ANTI_MAGIC) && !rn2(5)) {
  339.         You("escape a%s.", traps[ttype]);
  340.     } else {
  341.         seetrap(trap);
  342.         switch(ttype) {
  343.         case ARROW_TRAP:
  344.             pline("An arrow shoots out at you!");
  345.             otmp = mksobj(ARROW, TRUE, FALSE);
  346.             otmp->quan = 1L;
  347.             otmp->owt = weight(otmp);
  348.             if(thitu(8,dmgval(otmp,uasmon),otmp,"arrow")) {
  349.             obfree(otmp, (struct obj *)0);
  350.             } else {
  351.             place_object(otmp, u.ux, u.uy);
  352.             otmp->nobj = fobj;
  353.             fobj = otmp;        
  354.             stackobj(otmp);
  355.             newsym(u.ux, u.uy);
  356.             }
  357.             break;
  358.         case DART_TRAP:
  359.             pline("A little dart shoots out at you!");
  360.             otmp = mksobj(DART, TRUE, FALSE);
  361.             otmp->quan = 1L;
  362.             otmp->owt = weight(otmp);
  363.             if (!rn2(6)) otmp->opoisoned = 1;
  364.             if(thitu(7,dmgval(otmp,uasmon),otmp,"little dart")) {
  365.             if (otmp->opoisoned)
  366.                 poisoned("dart",A_CON,"poison dart",10);
  367.             obfree(otmp, (struct obj *)0);
  368.             } else {
  369.             place_object(otmp, u.ux, u.uy);
  370.             otmp->nobj = fobj;
  371.             fobj = otmp;        
  372.             stackobj(otmp);
  373.             newsym(u.ux, u.uy);
  374.             }
  375.             break;
  376.         case ROCKTRAP:
  377.             {
  378.             int dmg = d(2,6); /* should be std ROCK dmg? */
  379.  
  380.             otmp = mksobj_at(ROCK, u.ux, u.uy, TRUE);
  381.             otmp->quan = 1L;
  382.             otmp->owt = weight(otmp);
  383.  
  384.     pline("A trap door in the ceiling opens and a rock falls on your %s!",
  385.                 body_part(HEAD));
  386.  
  387.             if (uarmh) {
  388.                 if(is_metallic(uarmh)) {
  389.                 pline("Fortunately, you are wearing a hard helmet.");
  390.                 dmg = 2;
  391.                 } else if (flags.verbose) {
  392.                  Your("%s does not protect you.", xname(uarmh));
  393.                 }
  394.             }
  395.  
  396.             stackobj(otmp);
  397.             newsym(u.ux,u.uy);    /* map the rock */
  398.  
  399.             losehp(dmg, "falling rock", KILLED_BY_AN);
  400.             exercise(A_STR, FALSE);
  401.             }
  402.             break;
  403.  
  404.         case SQKY_BOARD:        /* stepped on a squeaky board */
  405.             if (Levitation
  406. #ifdef POLYSELF
  407.             || is_flyer(uasmon) || is_clinger(uasmon)
  408. #endif
  409.             ) {
  410.             if (Hallucination) You("notice a crease in the linoleum.");
  411.             else You("notice a loose board below you.");
  412.             } else {
  413.             pline("A board beneath you squeaks loudly.");
  414.             wake_nearby();
  415.             }
  416.             break;
  417.  
  418.         case BEAR_TRAP:
  419.             if(Levitation
  420. #ifdef POLYSELF
  421.                 || is_flyer(uasmon)) {
  422.             You("%s over a bear trap.",
  423.                   Levitation ? "float" : "fly");
  424. #else
  425.                 ) {
  426.             You("float over a bear trap.");
  427. #endif
  428.             break;
  429.             }
  430. #ifdef POLYSELF
  431.             if(amorphous(uasmon)) {
  432.             pline("A bear trap closes harmlessly through you.");
  433.             break;
  434.             }
  435. #endif
  436.             u.utrap = rn1(4, 4);
  437.             u.utraptype = TT_BEARTRAP;
  438.             pline("A bear trap closes on your %s!",
  439.             body_part(FOOT));
  440. #ifdef POLYSELF
  441.             if(u.umonnum == PM_OWLBEAR || u.umonnum == PM_BUGBEAR)
  442.             You("howl in anger!");
  443. #endif
  444.             exercise(A_DEX, FALSE);
  445.             break;
  446.  
  447.         case SLP_GAS_TRAP:
  448.             if(Sleep_resistance) {
  449.             You("are enveloped in a cloud of gas!");
  450.             break;
  451.             }
  452.             pline("A cloud of gas puts you to sleep!");
  453.             flags.soundok = 0;
  454.             nomul(-rnd(25));
  455.             u.usleep = 1;
  456.             nomovemsg = "You wake up.";
  457.             afternmv = Hear_again;
  458.             break;
  459.  
  460.         case RUST_TRAP:
  461. #ifdef POLYSELF
  462.             if (u.umonnum == PM_IRON_GOLEM) {
  463.             pline("A gush of water hits you!");
  464.             You("are covered with rust!");
  465.             rehumanize();
  466.             break;
  467.             } else
  468.             if (u.umonnum == PM_GREMLIN && rn2(3)) {
  469.             pline("A gush of water hits you!");
  470.             if ((mtmp = cloneu()) != 0) {
  471.                 mtmp->mhpmax = (u.mhmax /= 2);
  472.                 You("multiply.");
  473.             }
  474.             break;
  475.             }
  476. #endif
  477.         /* Unlike monsters, traps cannot aim their rust attacks at
  478.          * you, so instead of looping through and taking either the
  479.          * first rustable one or the body, we take whatever we get,
  480.          * even if it is not rustable.
  481.          */
  482.             switch (rn2(5)) {
  483.             case 0:
  484.                 pline("A gush of water hits you on the %s!",
  485.                     body_part(HEAD));
  486.                 (void) rust_dmg(uarmh, "helmet", 1, TRUE);
  487.                 break;
  488.             case 1:
  489.                 pline("A gush of water hits your left %s!",
  490.                     body_part(ARM));
  491.                 if (rust_dmg(uarms, "shield", 1, TRUE)) break;
  492.                 if (uwep && bimanual(uwep))
  493.                 goto two_hand;
  494.                 /* Two goto statements in a row--aaarrrgggh! */
  495. glovecheck:            (void) rust_dmg(uarmg, "gauntlets", 1, TRUE);
  496.                 /* Not "metal gauntlets" since it gets called
  497.                  * even if it's leather for the message
  498.                  */
  499.                 break;
  500.             case 2:
  501.                 pline("A gush of water hits your right %s!",
  502.                     body_part(ARM));
  503. two_hand:            erode_weapon(FALSE);
  504.                 goto glovecheck;
  505.             default:
  506.                 pline("A gush of water hits you!");
  507.                 if (uarmc) (void) rust_dmg(uarmc, "cloak", 1, TRUE);
  508.                 else if (uarm)
  509.                 (void) rust_dmg(uarm, "armor", 1, TRUE);
  510. #ifdef TOURIST
  511.                 else if (uarmu)
  512.                 (void) rust_dmg(uarmu, "shirt", 1, TRUE);
  513. #endif
  514.             }
  515.             break;
  516.  
  517.                 case FIRE_TRAP:
  518.                 dofiretrap();
  519.                 break;
  520.  
  521.         case PIT:
  522.             if (Levitation
  523. #ifdef POLYSELF
  524.             || is_flyer(uasmon) || is_clinger(uasmon)
  525. #endif
  526.             ) {
  527.             if(Blind) break;
  528.             if(trap->tseen) {
  529.                 You("see a pit below you.");
  530.             } else {
  531.                 pline("A pit opens up under you!");
  532.                 You("don't fall in!");
  533.             }
  534.             break;
  535.             }
  536.             You("fall into a pit!");
  537. #ifdef POLYSELF
  538.             if (!passes_walls(uasmon))
  539. #endif
  540.             u.utrap = rn1(6,2);
  541.             u.utraptype = TT_PIT;
  542.             losehp(rnd(6),"fell into a pit", NO_KILLER_PREFIX);
  543.             if (Punished && !carried(uball)) {
  544.             unplacebc();
  545.             ballfall();
  546.             placebc();
  547.             }
  548.             selftouch("Falling, you");
  549.             exercise(A_STR, FALSE);
  550.             vision_full_recalc = 1;    /* vision limits change */
  551.             break;
  552.         case SPIKED_PIT:
  553.             if (Levitation
  554. #ifdef POLYSELF
  555.             || is_flyer(uasmon) || is_clinger(uasmon)
  556. #endif
  557.             ) {
  558.             if(Blind) break;
  559.             pline("A pit full of spikes opens up under you!");
  560.             You("don't fall in!");
  561.             break;
  562.             }
  563.             You("fall into a pit!");
  564.             You("land on a set of sharp iron spikes!");
  565. #ifdef POLYSELF
  566.             if (!passes_walls(uasmon))
  567. #endif
  568.             u.utrap = rn1(6,2);
  569.             u.utraptype = TT_PIT;
  570.             losehp(rnd(10),"fell into a pit of iron spikes",
  571.             NO_KILLER_PREFIX);
  572.             if(!rn2(6)) poisoned("spikes",A_STR,"fall onto poison spikes",8);
  573.             if (Punished && !carried(uball)) {
  574.             unplacebc();
  575.             ballfall();
  576.             placebc();
  577.             }
  578.             selftouch("Falling, you");
  579.             vision_full_recalc = 1;    /* vision limits change */
  580.             exercise(A_STR, FALSE);
  581.             exercise(A_DEX, FALSE);
  582.             break;
  583.  
  584.         case TRAPDOOR:
  585.             if(!Can_fall_thru(&u.uz))
  586.             panic("Trapdoors cannot exist on this level.");
  587.             fall_through(TRUE);
  588.             break;
  589.  
  590.         case TELEP_TRAP:
  591.             if(In_endgame(&u.uz) || Antimagic) {
  592.             if(Antimagic)
  593.                 shieldeff(u.ux, u.uy);
  594.             You("feel a wrenching sensation.");
  595. #ifdef WALKIES
  596.             } else if(!next_to_u()) {
  597.                 You(shudder_for_moment);
  598. #endif
  599.             } else if(trap->once) {
  600.             deltrap(trap);
  601.             newsym(u.ux,u.uy);    /* get rid of trap symbol */
  602.             vtele();
  603.             } else
  604.             tele();
  605.             break;
  606.         case LEVEL_TELEP:
  607.             You("%s onto a level teleport trap!",
  608.               Levitation ? (const char *)"float" :
  609. #ifdef POLYSELF
  610.               locomotion(uasmon, "step"));
  611. #else
  612.               (const char *)"step");
  613. #endif
  614.             if(Antimagic) {
  615.             shieldeff(u.ux, u.uy);
  616.             }
  617.             if(Antimagic || In_endgame(&u.uz)) {
  618.             You("feel a wrenching sensation.");
  619.             break;
  620.             }
  621.             if(!Blind)
  622.                 You("are momentarily blinded by a flash of light.");
  623.             else
  624.             You("are momentarily disoriented.");
  625.             deltrap(trap);
  626.             newsym(u.ux,u.uy);    /* get rid of trap symbol */
  627.             level_tele();
  628.             break;
  629.  
  630.         case WEB: /* Our luckless player has stumbled into a web. */
  631. #ifdef POLYSELF
  632.             if (amorphous(uasmon)) {
  633.                 if (acidic(uasmon) || u.umonnum == PM_GELATINOUS_CUBE)
  634.             {
  635.                 deltrap(trap);
  636.                 newsym(u.ux,u.uy);/* update position */
  637.                 You("dissolve a spider web.");
  638.                 break;
  639.             }
  640.             You("flow through a spider web.");
  641.             break;
  642.             }
  643.             if (uasmon->mlet == S_SPIDER) {
  644.             pline("There is a spider web here.");
  645.             break;
  646.             }
  647. #endif
  648.             You("%s into a spider web!",
  649.               Levitation ? (const char *)"float" :
  650. #ifdef POLYSELF
  651.               locomotion(uasmon, "stumble"));
  652. #else
  653.               (const char *)"stumble");
  654. #endif
  655.             u.utraptype = TT_WEB;
  656.  
  657.             /* Time stuck in the web depends on your strength. */
  658.             {
  659.             register int str = ACURR(A_STR);
  660.  
  661.             if (str == 3) u.utrap = rn1(6,6);
  662.             else if (str < 6) u.utrap = rn1(6,4);
  663.             else if (str < 9) u.utrap = rn1(4,4);
  664.             else if (str < 12) u.utrap = rn1(4,2);
  665.             else if (str < 15) u.utrap = rn1(2,2);
  666.             else if (str < 18) u.utrap = rnd(2);
  667.             else if (str < 69) u.utrap = 1;
  668.             else {
  669.             u.utrap = 0;
  670.             You("tear through the web!");
  671.             deltrap(trap);
  672.             newsym(u.ux,u.uy);    /* get rid of trap symbol */
  673.             }
  674.             }
  675.             break;
  676.  
  677.         case STATUE_TRAP:
  678.             deltrap(trap);
  679.             newsym(u.ux,u.uy);    /* get rid of trap symbol */
  680.             for (otmp = level.objects[u.ux][u.uy];
  681.                         otmp; otmp = otmp->nexthere)
  682.             if (otmp->otyp == STATUE)
  683.                 if ((mtmp = makemon(&mons[otmp->corpsenm],
  684.                         u.ux, u.uy)) != 0) {
  685.                 pline("The statue comes to life!");
  686.                 /* mimic statues become seen mimics */
  687.                 if(mtmp->m_ap_type) seemimic(mtmp);
  688.                 delobj(otmp);
  689.                 break;
  690.                 }
  691.             break;
  692.  
  693.         case MAGIC_TRAP:        /* A magic trap. */
  694.             if (!rn2(30)) {
  695.             deltrap(trap);
  696.             newsym(u.ux,u.uy);    /* update position */
  697.             You("are caught in a magical explosion!");
  698.             losehp(rnd(10), "magical explosion", KILLED_BY_AN);
  699.             Your("body absorbs some of the magical energy!");
  700.             u.uen = (u.uenmax += 2);
  701.             } else domagictrap();
  702.             break;
  703.  
  704.         case ANTI_MAGIC:
  705.             if(Antimagic) {
  706.             shieldeff(u.ux, u.uy);
  707.             You("feel momentarily lethargic.");
  708.             } else drain_en(rnd((int)u.ulevel) + 1);
  709.             break;
  710.  
  711. #ifdef POLYSELF
  712.         case POLY_TRAP:
  713.             if(Antimagic) {
  714.             shieldeff(u.ux, u.uy);
  715.             You("feel momentarily different.");
  716.             /* Trap did nothing; don't remove it --KAA */
  717.             } else {
  718.             deltrap(trap);    /* delete trap before polymorph */
  719.             newsym(u.ux,u.uy);    /* get rid of trap symbol */
  720.             You("feel a change coming over you.");
  721.             polyself();
  722.             }
  723.             break;
  724. #endif
  725.  
  726.         case LANDMINE: {
  727.             if (Levitation
  728. #ifdef POLYSELF
  729.                     || is_flyer(uasmon)
  730. #endif
  731.                                 ) {
  732.             You("see a trigger in a pile of soil below you.");
  733.             if (rn2(3)) break;
  734.             pline("KAABLAMM!!!  The air currents set it off!");
  735.             } else {
  736.             pline("KAABLAMM!!!  You triggered a land mine!");
  737.             set_wounded_legs(LEFT_SIDE, rn1(35, 41));
  738.             set_wounded_legs(RIGHT_SIDE, rn1(35, 41));
  739.             exercise(A_DEX, FALSE);
  740.             }
  741.             losehp(rnd(16), "land mine", KILLED_BY_AN);
  742.             /* wake everything on the level */
  743.             for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
  744.             if(mtmp->msleep) mtmp->msleep = 0;
  745.             }
  746.             deltrap(t_at(u.ux, u.uy));    /* mines only explode once */
  747.             newsym(u.ux,u.uy);        /* get rid of trap symbol */
  748.           }
  749.             break;
  750.  
  751.                 case MAGIC_PORTAL:
  752. #ifdef WALKIES
  753.             if(!next_to_u())
  754.                 You(shudder_for_moment);
  755.             else
  756. #endif
  757.                 domagicportal(trap);
  758.                 break;
  759.  
  760.         default:
  761.             impossible("You hit a trap of type %u", trap->ttyp);
  762.         }
  763.     }
  764. }
  765.  
  766. #endif /* OVLB */
  767.  
  768. #ifdef WALKIES
  769.  
  770. STATIC_DCL boolean FDECL(teleport_pet, (struct monst *));
  771.  
  772. #ifdef OVLB
  773.  
  774. STATIC_OVL boolean
  775. teleport_pet(mtmp)
  776. register struct monst *mtmp;
  777. {
  778.     register struct obj *otmp;
  779.  
  780.     if(mtmp->mleashed) {
  781.         otmp = get_mleash(mtmp);
  782.         if(!otmp)
  783.         impossible("%s is leashed, without a leash.", Monnam(mtmp));
  784.         if(otmp->cursed) {
  785. # ifdef SOUNDS
  786.         yelp(mtmp);
  787. # endif
  788.         return FALSE;
  789.         } else {
  790.         Your("leash goes slack.");
  791.         m_unleash(mtmp);
  792.         return TRUE;
  793.         }
  794.     }
  795.     return TRUE;
  796. }
  797.  
  798. #endif /* OVLB */
  799.  
  800. #endif /* WALKIES */
  801.  
  802. #ifdef OVLB
  803.  
  804. void
  805. seetrap(trap)
  806.     register struct trap *trap;
  807. {
  808.     if(!trap->tseen) {
  809.         trap->tseen = 1;
  810.         newsym(trap->tx, trap->ty);
  811.     }
  812. }
  813.  
  814. #endif /* OVLB */
  815. #ifdef OVL1
  816.  
  817. int
  818. mintrap(mtmp)
  819. register struct monst *mtmp;
  820. {
  821.     register struct trap *trap = t_at(mtmp->mx, mtmp->my);
  822.     boolean trapkilled = FALSE;
  823.     struct permonst *mptr = mtmp->data;
  824.     struct obj *otmp;
  825.  
  826.     if(!trap) {
  827.         mtmp->mtrapped = 0;    /* perhaps teleported? */
  828.     } else if (mtmp->mtrapped) {    /* was in trap */
  829.         if(!rn2(40)) {
  830.             if (sobj_at(BOULDER, mtmp->mx, mtmp->my) && 
  831.                 ((trap->ttyp == PIT) || 
  832.                  (trap->ttyp == SPIKED_PIT))) {
  833.                 if (!rn2(2)) {
  834.                     mtmp->mtrapped = 0;
  835.                     fill_pit(mtmp->mx, mtmp->my);
  836.                 }
  837.             } else
  838.                 mtmp->mtrapped = 0;
  839.         }
  840.     } else {
  841.         register int tt = trap->ttyp;
  842.  
  843.         /* A bug fix for dumb messages by ab@unido.
  844.          */
  845.         int in_sight = canseemon(mtmp);
  846.  
  847.         if(mtmp->mtrapseen & (1 << tt)) {
  848.         /* it has been in such a trap - perhaps it escapes */
  849.         if(rn2(4)) return(0);
  850.         }
  851.         mtmp->mtrapseen |= (1 << tt);
  852.         switch (tt) {
  853.         case ARROW_TRAP:
  854.             otmp = mksobj(ARROW, TRUE, FALSE);
  855.             otmp->quan = 1L;
  856.             otmp->owt = weight(otmp);
  857.             if(in_sight) seetrap(trap);
  858.             if(thitm(8, mtmp, otmp, 0)) trapkilled = TRUE;
  859.             break;
  860.         case DART_TRAP:
  861.             otmp = mksobj(DART, TRUE, FALSE);
  862.             otmp->quan = 1L;
  863.             otmp->owt = weight(otmp);
  864.             if (!rn2(6)) otmp->opoisoned = 1;
  865.             if(in_sight) seetrap(trap);
  866.             if(thitm(7, mtmp, otmp, 0)) trapkilled = TRUE;
  867.             break;
  868.         case ROCKTRAP:
  869.             otmp = mksobj(ROCK, TRUE, FALSE);
  870.             otmp->quan = 1L;
  871.             otmp->owt = weight(otmp);
  872.             if(in_sight) seetrap(trap);
  873.             if(!is_whirly(mptr) && !passes_walls(mptr) &&
  874.                thitm(0, mtmp, otmp, d(2, 6)))
  875.                 trapkilled = TRUE;
  876.             break;
  877.  
  878.         case SQKY_BOARD: {
  879.             register struct monst *ztmp = fmon;
  880.  
  881.             if(is_flyer(mptr)) break;
  882.             /* stepped on a squeaky board */
  883.             if (in_sight) {
  884.                 pline("A board beneath %s squeaks loudly.", mon_nam(mtmp));
  885.                 seetrap(trap);
  886.             } else
  887.                You("hear a distant squeak.");
  888.             /* wake up nearby monsters */
  889.             while(ztmp) {
  890.                 if(dist2(mtmp->mx,mtmp->my,ztmp->mx,ztmp->my) < 40)
  891.                 if(ztmp->msleep) ztmp->msleep = 0;
  892.                 ztmp = ztmp->nmon;
  893.             }
  894.             break;
  895.         }
  896.  
  897.         case BEAR_TRAP:
  898.             if(mptr->msize > MZ_SMALL &&
  899.                !amorphous(mptr) && !is_flyer(mptr)) {
  900.                 mtmp->mtrapped = 1;
  901.                 if(in_sight) {
  902.                 pline("%s is caught in a bear trap!",
  903.                       Monnam(mtmp));
  904.                 seetrap(trap);
  905.                 } else {
  906.                 if((mptr == &mons[PM_OWLBEAR]
  907.                     || mptr == &mons[PM_BUGBEAR])
  908.                    && flags.soundok)
  909.                     You("hear the roaring of an angry bear!");
  910.                 }
  911.             }
  912.             break;
  913.  
  914.         case SLP_GAS_TRAP:
  915.             if(!resists_sleep(mptr) &&
  916.                !mtmp->msleep && mtmp->mcanmove) {
  917.                 mtmp->mcanmove = 0;
  918.                 mtmp->mfrozen = rnd(25);
  919.                 if (in_sight) {
  920.                     pline("%s suddenly falls asleep!",
  921.                                 Monnam(mtmp));
  922.                     seetrap(trap);
  923.                 }
  924.             }
  925.             break;
  926.  
  927.         case RUST_TRAP:
  928.             if (in_sight) {
  929.                 pline("A gush of water hits %s!", mon_nam(mtmp));
  930.                 seetrap(trap);
  931.             }
  932.             if (mptr == &mons[PM_IRON_GOLEM]) {
  933.                 if (in_sight)
  934.                     pline("%s falls to pieces!", Monnam(mtmp));
  935.                 else if(mtmp->mtame)
  936.                     pline("May %s rust in peace.",
  937.                                 mon_nam(mtmp));
  938.                 mondied(mtmp);
  939. #ifdef MUSE
  940.                 if (mtmp->mhp <= 0)
  941. #endif
  942.                     trapkilled = TRUE;
  943.             } else if (mptr == &mons[PM_GREMLIN] && rn2(3)) {
  944.                 struct monst *mtmp2 = clone_mon(mtmp);
  945.  
  946.                 if (mtmp2) {
  947.                     mtmp2->mhpmax = (mtmp->mhpmax /= 2);
  948.                     if(in_sight)
  949.                     pline("%s multiplies.", Monnam(mtmp));
  950.                 }
  951.             }
  952.             break;
  953.  
  954.         case FIRE_TRAP:
  955.             if (in_sight)
  956.              pline("A tower of flame bursts from the %s under %s!",
  957.                 surface(mtmp->mx,mtmp->my), mon_nam(mtmp));
  958.             if(resists_fire(mptr)) {
  959.                 if (in_sight) {
  960.                 shieldeff(mtmp->mx,mtmp->my);
  961.                 pline("%s is uninjured.", Monnam(mtmp));
  962.                 }
  963.             } else {
  964.                 int num=rnd(6);
  965.  
  966.                 if (thitm(0, mtmp, (struct obj *)0, num))
  967.                 trapkilled = TRUE;
  968.                 else mtmp->mhpmax -= num;
  969.             }
  970.             (void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE);
  971.             (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE);
  972.             (void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE);
  973.             if (is_ice(mtmp->mx,mtmp->my))
  974.                 melt_ice(mtmp->mx,mtmp->my);
  975.             if (in_sight) seetrap(trap);
  976.             break;
  977.  
  978.         case PIT:
  979.         case SPIKED_PIT:
  980.             if ( !is_flyer(mptr) && 
  981.                  (!mtmp->wormno || (count_wsegs(mtmp) < 6)) &&
  982.                  !is_clinger(mptr) ) {
  983.                 if (!passes_walls(mptr))
  984.                     mtmp->mtrapped = 1;
  985.                 if(in_sight) {
  986.                     pline("%s falls into a pit!", Monnam(mtmp));
  987.                     seetrap(trap);
  988.                 }
  989. #ifdef MUSE
  990.                 mselftouch(mtmp, "Falling, ", FALSE);
  991.                 if(mtmp->mhp <= 0 ||
  992.                     thitm(0, mtmp, (struct obj *)0,
  993.                      rnd((tt==PIT) ? 6 : 10)))
  994. #else
  995.                 if(thitm(0, mtmp, (struct obj *)0,
  996.                      rnd((tt==PIT) ? 6 : 10)))
  997. #endif
  998.                     trapkilled = TRUE;
  999.             }
  1000.             break;
  1001.  
  1002.         case TRAPDOOR:
  1003.             if(!Can_fall_thru(&u.uz))
  1004.                 panic("Trapdoors cannot exist on this level.");
  1005.  
  1006.             if (is_flyer(mptr) || mptr == &mons[PM_WUMPUS] ||
  1007.                 (mtmp->wormno && count_wsegs(mtmp) > 5)) break;
  1008.             /* Fall through */
  1009.         case LEVEL_TELEP:
  1010.         case MAGIC_PORTAL:
  1011.             if (mtmp == u.ustuck)    /* probably a vortex */
  1012.                 break;        /* temporary? kludge */
  1013. #ifdef WALKIES
  1014.             if (teleport_pet(mtmp))
  1015. #endif
  1016.             {
  1017.                 d_level tolevel;
  1018.                 int migrate_typ = 0;
  1019.  
  1020.                 if (tt == TRAPDOOR) {
  1021.                 if (Is_stronghold(&u.uz)) {
  1022.                     assign_level(&tolevel, &valley_level);
  1023.                 } else if (Is_botlevel(&u.uz)) {
  1024.                     pline("%s avoids the trap.", Monnam(mtmp));
  1025.                     break;
  1026.                 } else {
  1027.                     get_level(&tolevel, depth(&u.uz) + 1);
  1028.                 }
  1029.                 } else if (tt == MAGIC_PORTAL) {
  1030.                 if (In_endgame(&u.uz) &&
  1031.                     (mon_has_amulet(mtmp) ||
  1032.                     is_home_elemental(mptr))) {
  1033.                     if (in_sight && mptr->mlet != S_ELEMENTAL) {
  1034.                      pline("%s seems to shimmer for a moment.",
  1035.                        Monnam(mtmp));
  1036.                     seetrap(trap);
  1037.                     }
  1038.                     break;
  1039.                 } else {
  1040.                     assign_level(&tolevel, &trap->dst);
  1041.                     migrate_typ = 6; /* see dog.c */
  1042.                 }
  1043.                 } else { /* (tt == LEVEL_TELEP) */
  1044.                 register int nlev;
  1045.  
  1046.                 if (mon_has_amulet(mtmp)) break;
  1047.                 nlev = rnd(3);
  1048.                 if (!rn2(2)) nlev = -nlev;
  1049.                 nlev += dunlev(&u.uz);
  1050.                 if (nlev > dunlevs_in_dungeon(&u.uz)) {
  1051.                     nlev = dunlevs_in_dungeon(&u.uz);
  1052.                     /* teleport up if already on bottom */
  1053.                     if (Is_botlevel(&u.uz)) nlev -= rnd(3);
  1054.                 }
  1055.                 if (nlev < 1) {
  1056.                     nlev = 1;
  1057.                     if (dunlev(&u.uz) == 1) {
  1058.                     nlev += rnd(3);
  1059.                     if (nlev > dunlevs_in_dungeon(&u.uz)) 
  1060.                         nlev = dunlevs_in_dungeon(&u.uz);
  1061.                     }
  1062.                 }
  1063.                 /* can't seem to go anywhere    */
  1064.                 /* (possible in short dungeons) */
  1065.                 if (nlev == dunlev(&u.uz)) {
  1066.                     rloc(mtmp);
  1067.                     break;
  1068.                 }
  1069.                 nlev += dungeons[u.uz.dnum].depth_start;
  1070.                 get_level(&tolevel, nlev);
  1071.                 }
  1072.  
  1073.                 if (in_sight) {
  1074.                 pline("Suddenly, %s disappears out of sight.",
  1075.                       mon_nam(mtmp));
  1076.                 seetrap(trap);
  1077.                 }
  1078.                 migrate_to_level(mtmp, 
  1079.                          ledger_no(&tolevel),
  1080.                          migrate_typ);
  1081.                 return(3);    /* no longer on this level */
  1082.             }
  1083.             break;
  1084.  
  1085.         case TELEP_TRAP:
  1086.             if(tele_restrict(mtmp)) break;
  1087. #ifdef WALKIES
  1088.             if(teleport_pet(mtmp)) {
  1089. #endif
  1090.                 /* Note: don't remove the trap if a vault.  Other-
  1091.                  * wise the monster will be stuck there, since 
  1092.                  * the guard isn't going to come for it...
  1093.                  */
  1094.                 if (in_sight) {
  1095.                 pline("%s suddenly disappears!", 
  1096.                                       Monnam(mtmp));
  1097.                 seetrap(trap);
  1098.                 }
  1099.                 if (trap->once) vloc(mtmp);
  1100.                 else rloc(mtmp);
  1101. #ifdef WALKIES
  1102.             }
  1103. #endif
  1104.             break;
  1105.  
  1106.         case WEB:
  1107.             /* Monster in a web. */
  1108.             if (mptr->mlet == S_SPIDER) break;
  1109.             if (amorphous(mptr)) {
  1110.                 if (acidic(mptr) ||
  1111.                  mptr == &mons[PM_GELATINOUS_CUBE]) {
  1112.                 if (in_sight)
  1113.                     pline("%s dissolves a spider web.",
  1114.                         Monnam(mtmp));
  1115.                 deltrap(trap);
  1116.                 break;
  1117.                 }
  1118.                 if (in_sight)
  1119.                 pline("%s flows through a spider web.",
  1120.                         Monnam(mtmp));
  1121.                 break;
  1122.             }            
  1123.             switch (monsndx(mptr)) {
  1124.                 case PM_FIRE_ELEMENTAL:
  1125.                 if (in_sight)
  1126.                     pline("%s burns a spider web!", Monnam(mtmp));
  1127.                 deltrap(trap);
  1128.                 break;
  1129.                 case PM_OWLBEAR: /* Eric Backus */
  1130.                 case PM_BUGBEAR:
  1131.                 if (!in_sight) {
  1132.                     You("hear the roaring of a confused bear!");
  1133.                     mtmp->mtrapped = 1;
  1134.                     break;
  1135.                 }
  1136.                 /* fall though */
  1137.                 default:
  1138.                 if (in_sight)
  1139.                     pline("%s is caught in a spider web.",
  1140.                                 Monnam(mtmp));
  1141.                 mtmp->mtrapped = 1;
  1142.                 break;
  1143.             }
  1144.             break;
  1145.  
  1146.         case STATUE_TRAP:
  1147.             break;
  1148.  
  1149.         case MAGIC_TRAP:
  1150.             /* A magic trap.  Monsters immune. */
  1151.             break;
  1152.         case ANTI_MAGIC:
  1153.             break;
  1154.  
  1155.         case LANDMINE: {
  1156.             register struct monst *mntmp = fmon;
  1157.  
  1158.             if(rn2(3))
  1159.                 break; /* monsters usually don't set it off */
  1160.             if(is_flyer(mptr)) {
  1161.                 if (in_sight) {
  1162.     pline("A trigger appears in a pile of soil below %s.", mon_nam(mtmp));
  1163.                     seetrap(trap);
  1164.                 }
  1165.                 if (rn2(3)) break;
  1166.                 if (in_sight)
  1167.                     pline("The air currents set it off!");
  1168.             } else if(in_sight)
  1169.                 pline("KAABLAMM!!!  %s triggers a land mine!",
  1170.                   Monnam(mtmp));
  1171.             if (!in_sight)
  1172.                 pline("Kaablamm!  You hear an explosion in the distance!");
  1173.             deltrap(trap);
  1174.             if(thitm(0, mtmp, (struct obj *)0, rnd(16)))
  1175.                 trapkilled = TRUE;
  1176.             /* wake everything on the level */
  1177.             while(mntmp) {
  1178.                 if(mntmp->msleep)
  1179.                     mntmp->msleep = 0;
  1180.                 mntmp = mntmp->nmon;
  1181.             }
  1182.             if (unconscious()) {
  1183.                 multi = -1;
  1184.                 nomovemsg="The explosion awakens you!";
  1185.             }
  1186.             break;
  1187.         }
  1188.  
  1189. #ifdef POLYSELF
  1190.         case POLY_TRAP:
  1191.             if(!resist(mtmp, WAND_CLASS, 0, NOTELL)) {
  1192.             (void) newcham(mtmp, (struct permonst *)0);
  1193.             if (in_sight) seetrap(trap);
  1194.             }
  1195.             break;
  1196. #endif
  1197.  
  1198.         default:
  1199.             impossible("Some monster encountered a strange trap of type %d.", tt);
  1200.         }
  1201.     }
  1202.     if(trapkilled) return 2;
  1203.     return mtmp->mtrapped;
  1204. }
  1205.  
  1206. #endif /* OVL1 */
  1207. #ifdef OVLB
  1208.  
  1209. void
  1210. selftouch(arg)
  1211. const char *arg;
  1212. {
  1213.     if(uwep && uwep->otyp == CORPSE && uwep->corpsenm == PM_COCKATRICE
  1214. #ifdef POLYSELF
  1215.             && !resists_ston(uasmon)
  1216. #endif
  1217.     ){
  1218.         pline("%s touch the cockatrice corpse.", arg);
  1219. #ifdef POLYSELF
  1220.         if(poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM))
  1221.             return;
  1222. #endif
  1223.         You("turn to stone...");
  1224.         killer_format = KILLED_BY;
  1225.         killer = "touching a cockatrice corpse";
  1226.         done(STONING);
  1227.     }
  1228. }
  1229.  
  1230. #ifdef MUSE
  1231. void
  1232. mselftouch(mon,arg,byplayer)
  1233. struct monst *mon;
  1234. const char *arg;
  1235. boolean byplayer;
  1236. {
  1237.     struct obj *mwep = MON_WEP(mon);
  1238.  
  1239.     if (mwep && mwep->otyp == CORPSE && mwep->corpsenm == PM_COCKATRICE
  1240.             && !resists_ston(mon->data)) {
  1241.         if (cansee(mon->mx, mon->my)) {
  1242.             pline("%s%s touches the cockatrice corpse.",
  1243.                 arg ? arg : "", arg ? mon_nam(mon) : Monnam(mon));
  1244.             pline("%s turns to stone.", Monnam(mon));
  1245.         }
  1246.         if (poly_when_stoned(mon->data)) {
  1247.             mon_to_stone(mon);
  1248.             return;
  1249.         }
  1250.         if (byplayer) {
  1251.             stoned = TRUE;
  1252.             xkilled(mon,0);
  1253.         } else monstone(mon);
  1254.     }
  1255. }
  1256. #endif
  1257.  
  1258. void
  1259. float_up()
  1260. {
  1261.     if(u.utrap) {
  1262.         if(u.utraptype == TT_PIT) {
  1263.             u.utrap = 0;
  1264.             You("float up, out of the pit!");
  1265.             vision_full_recalc = 1;    /* vision limits change */
  1266.             fill_pit(u.ux, u.uy);
  1267.         } else if (u.utraptype == TT_INFLOOR) {
  1268.             Your("body pulls upward, but your %s are still stuck.",
  1269.                  makeplural(body_part(LEG)));
  1270.         } else {
  1271.             You("float up, only your %s is still stuck.",
  1272.                 body_part(LEG));
  1273.         }
  1274.     }
  1275.     else if(Is_waterlevel(&u.uz))
  1276.         pline("It feels as though you'd lost some weight.");
  1277.     else if(u.uinwater)
  1278.         spoteffects();
  1279.     else if (Hallucination)
  1280.         pline("Up, up, and awaaaay!  You're walking on air!");
  1281.     else if(Is_airlevel(&u.uz))
  1282.         You("gain control over your movements.");
  1283.     else
  1284.         You("start to float in the air!");
  1285. }
  1286.  
  1287. void
  1288. fill_pit(x, y)
  1289. int x, y;
  1290. {
  1291.     struct obj *otmp;
  1292.     struct trap *t;
  1293.  
  1294.     if ((t = t_at(x, y)) && 
  1295.         ((t->ttyp == PIT) || (t->ttyp == SPIKED_PIT)) &&
  1296.         (otmp = sobj_at(BOULDER, x, y))) {
  1297.         freeobj(otmp);
  1298.         (void) flooreffects(otmp, x, y, "settle");
  1299.     }
  1300. }
  1301.  
  1302. int
  1303. float_down()
  1304. {
  1305.     register struct trap *trap = (struct trap *)0;
  1306.     boolean no_msg = FALSE;
  1307.  
  1308.     if(Levitation) return(0); /* maybe another ring/potion/boots */
  1309.  
  1310.     if (Punished && !carried(uball) &&
  1311.         (is_pool(uball->ox, uball->oy) || 
  1312.          ((trap = t_at(uball->ox, uball->oy)) && 
  1313.           ((trap->ttyp == PIT) || (trap->ttyp == SPIKED_PIT) ||
  1314.            (trap->ttyp == TRAPDOOR))))) {
  1315.             u.ux0 = u.ux;
  1316.             u.uy0 = u.uy;
  1317.             u.ux = uball->ox;
  1318.             u.uy = uball->oy;
  1319.             movobj(uchain, uball->ox, uball->oy);
  1320.             newsym(u.ux0, u.uy0);
  1321.             vision_full_recalc = 1;    /* in case the hero moved. */
  1322.     }
  1323.     /* check for falling into pool - added by GAN 10/20/86 */
  1324. #ifdef POLYSELF
  1325.     if(!is_flyer(uasmon)) {
  1326. #endif
  1327.         /* kludge alert:
  1328.          * drown() and lava_effects() print various messages almost
  1329.          * every time they're called which conflict with the "fall
  1330.          * into" message below.  Thus, we want to avoid printing
  1331.          * confusing, duplicate or out-of-order messages.
  1332.          * Use knowledge of the two routines as a hack -- this
  1333.          * should really handled differently -dlc
  1334.          */
  1335.         if(is_pool(u.ux,u.uy) && !Wwalking && !u.uinwater)
  1336.             no_msg = drown();
  1337.  
  1338.         if(is_lava(u.ux,u.uy)) {
  1339.             (void) lava_effects();
  1340.             no_msg = TRUE;
  1341.         }
  1342. #ifdef POLYSELF
  1343.     }
  1344. #endif
  1345.     if (!trap) {
  1346.         if(Is_airlevel(&u.uz))
  1347.             You("begin to tumble in place.");
  1348.         else if (Is_waterlevel(&u.uz) && !no_msg)
  1349.             You("feel heavier.");
  1350.         /* u.uinwater msgs already in spoteffects()/drown() */
  1351.         else if (!u.uinwater && !no_msg) {
  1352.             if (Hallucination)
  1353.                 pline("Bummer!  You've %s.",
  1354.                       is_pool(u.ux,u.uy) ?
  1355.                     "splashed down" : "hit the ground");
  1356.             else
  1357.                 You("float gently to the %s.",
  1358.                     surface(u.ux, u.uy));
  1359.         }
  1360.         trap = t_at(u.ux,u.uy);
  1361.     }
  1362.  
  1363.     if(trap)
  1364.         switch(trap->ttyp) {
  1365.         case STATUE_TRAP:
  1366.             break;
  1367.         case TRAPDOOR:
  1368.             if(!Can_fall_thru(&u.uz) || u.ustuck)
  1369.                 break;
  1370.             /* fall into next case */
  1371.         default:
  1372.             dotrap(trap);
  1373.     }
  1374.     if(!Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz))
  1375.         pickup(1);
  1376.     return 0;
  1377. }
  1378.  
  1379.  
  1380. void
  1381. tele()
  1382. {
  1383.     coord cc;
  1384.  
  1385.     /* Disable teleportation in stronghold && Vlad's Tower */
  1386.     if(level.flags.noteleport) {
  1387. #ifdef WIZARD
  1388.         if (!wizard) {
  1389. #endif
  1390.             pline("A mysterious force prevents you from teleporting!");
  1391.             return;
  1392. #ifdef WIZARD
  1393.         }
  1394. #endif
  1395.     }
  1396.  
  1397.     /* don't show trap if "Sorry..." */
  1398.     if(!Blinded) make_blinded(0L,FALSE);
  1399.  
  1400.     if((u.uhave.amulet || Is_wiz1_level(&u.uz) || Is_wiz2_level(&u.uz) ||
  1401.            Is_wiz3_level(&u.uz)) && !rn2(3)) {
  1402.         You("feel disoriented for a moment.");
  1403.         return;
  1404.     }
  1405.     if(Teleport_control
  1406. #ifdef WIZARD
  1407.                 || wizard
  1408. #endif
  1409.                     ) {
  1410.         if (unconscious()) {
  1411.         pline("Being unconscious, you cannot control your teleport.");
  1412.         } else {
  1413.             pline("To what position do you want to be teleported?");
  1414.             cc.x = u.ux;
  1415.             cc.y = u.uy;
  1416.             getpos(&cc, TRUE, "the desired position");/* force valid*/
  1417.                     if(cc.x == -10) return; /* abort */
  1418.             /* possible extensions: introduce a small error if
  1419.                magic power is low; allow transfer to solid rock */
  1420.             if(teleok(cc.x, cc.y, FALSE)){
  1421.             teleds(cc.x, cc.y);
  1422.             return;
  1423.             }
  1424.             pline("Sorry...");
  1425.         }
  1426.     }
  1427.  
  1428.     (void) safe_teleds();
  1429. }
  1430.  
  1431. boolean
  1432. tele_restrict(mon)
  1433. struct monst *mon;
  1434. {
  1435.     if(level.flags.noteleport) {
  1436.         if (canseemon(mon))
  1437.             pline("A mysterious force prevents %s from teleporting!",
  1438.             mon_nam(mon));
  1439.         return TRUE;
  1440.     }
  1441.     return FALSE;
  1442. }
  1443.  
  1444. void
  1445. teleds(nux, nuy)
  1446. register int nux,nuy;
  1447. {
  1448.     if (Punished) unplacebc();
  1449.     u.utrap = 0;
  1450.     u.ustuck = 0;
  1451.     u.ux0 = u.ux;
  1452.     u.uy0 = u.uy;
  1453.     u.ux = nux;
  1454.     u.uy = nuy;
  1455.     fill_pit(u.ux0, u.uy0); /* do this now so that cansee() is correct */
  1456. #ifdef POLYSELF
  1457.     if (hides_under(uasmon))
  1458.         u.uundetected = OBJ_AT(nux, nuy);
  1459.     else 
  1460.         u.uundetected = 0;
  1461.     if (u.usym == S_MIMIC_DEF) u.usym = S_MIMIC;
  1462. #endif
  1463.     if(u.uswallow){
  1464.         u.uswldtim = u.uswallow = 0;
  1465.         docrt();
  1466.     }
  1467.     if(Punished) placebc();
  1468.     initrack(); /* teleports mess up tracking monsters without this */
  1469.     /*
  1470.      *  Make sure the hero disappears from the old location.  This will
  1471.      *  not happen if she is teleported within sight of her previous
  1472.      *  location.  Force a full vision recalculation because the hero
  1473.      *  is now in a new location.
  1474.      */
  1475.     newsym(u.ux0,u.uy0);
  1476.     vision_full_recalc = 1;
  1477.     nomul(0);
  1478.     spoteffects();
  1479. }
  1480.  
  1481. int
  1482. dotele()
  1483. {
  1484.     struct trap *trap;
  1485.     boolean castit = FALSE;
  1486.     register int sp_no = 0, energy;
  1487.  
  1488.     trap = t_at(u.ux, u.uy);
  1489.     if (trap && (!trap->tseen || trap->ttyp != TELEP_TRAP))
  1490.         trap = 0;
  1491.  
  1492.     if (trap) {
  1493.         if (trap->once) {
  1494.             pline("This is a vault teleport, usable once only.");
  1495.             if (yn("Jump in?") == 'n')
  1496.                 trap = 0;
  1497.             else {
  1498.                 deltrap(trap);
  1499.                 newsym(u.ux, u.uy);
  1500.             }
  1501.         }
  1502.         if (trap)
  1503. #ifdef POLYSELF
  1504.             You("%s onto the teleportation trap.",
  1505.                 locomotion(uasmon, "jump"));
  1506. #else
  1507.             You("jump onto the teleportation trap.");
  1508. #endif
  1509.     }
  1510.     if(!trap && (!Teleportation ||
  1511.        (u.ulevel < (pl_character[0] == 'W' ? 8 : 12)
  1512. #ifdef POLYSELF
  1513.         && !can_teleport(uasmon)
  1514. #endif
  1515.        )
  1516.       )) {
  1517.         /* Try to use teleport away spell. */
  1518.         castit = objects[SPE_TELEPORT_AWAY].oc_name_known;
  1519.         if (castit) {
  1520.             for (sp_no = 0; sp_no < MAXSPELL &&
  1521.                 spl_book[sp_no].sp_id != NO_SPELL &&
  1522.                 spl_book[sp_no].sp_id != SPE_TELEPORT_AWAY; sp_no++);
  1523.  
  1524.             if (sp_no == MAXSPELL ||
  1525.             spl_book[sp_no].sp_id != SPE_TELEPORT_AWAY)
  1526.                 castit = FALSE;
  1527.         }
  1528. #ifdef WIZARD
  1529.         if (!wizard) {
  1530. #endif
  1531.             if (!castit) {
  1532.             if (!Teleportation)
  1533.                 You("don't know that spell.");
  1534.             else You("are not able to teleport at will.");
  1535.             return(0);
  1536.             }
  1537. #ifdef WIZARD
  1538.         }
  1539. #endif
  1540.     }
  1541.  
  1542.     if(!trap && (u.uhunger <= 100 || ACURR(A_STR) < 6)) {
  1543. #ifdef WIZARD
  1544.         if (!wizard) {
  1545. #endif
  1546.             You("lack the strength %s.",
  1547.                 castit ? "for a teleport spell" : "to teleport");
  1548.             return 1;
  1549. #ifdef WIZARD
  1550.         }
  1551. #endif
  1552.     }
  1553.  
  1554.     energy = objects[SPE_TELEPORT_AWAY].oc_level * 7 / 2 - 2;
  1555.  
  1556.     if(!trap && u.uen <= energy) {
  1557. #ifdef WIZARD
  1558.         if (!wizard) {
  1559. #endif
  1560.             You("lack the energy %s.",
  1561.                 castit ? "for a teleport spell" : "to teleport");
  1562.             return 1;
  1563. #ifdef WIZARD
  1564.         } else u.uen = energy;
  1565. #endif
  1566.     }
  1567.  
  1568.     if(!trap &&
  1569.       check_capacity("Your concentration falters from carrying so much."))
  1570.         return 1;
  1571.  
  1572.     if (castit) {
  1573.         exercise(A_WIS, TRUE);
  1574.         if (spelleffects(++sp_no, TRUE))
  1575.             return(1);
  1576.         else
  1577. #ifdef WIZARD
  1578.             if (!wizard)
  1579. #endif
  1580.             return(0);
  1581.     } else if (!trap)
  1582.         u.uen -= energy;
  1583.  
  1584. #ifdef WALKIES
  1585.     if(next_to_u()) {
  1586. #endif
  1587.         if (trap && trap->once) vtele();
  1588.         else tele();
  1589. #ifdef WALKIES
  1590.         (void) next_to_u();
  1591.     } else {
  1592.         You(shudder_for_moment);
  1593.         return(0);
  1594.     }
  1595. #endif
  1596.     if (!trap) morehungry(100);
  1597.     return(1);
  1598. }
  1599.  
  1600.  
  1601. void
  1602. level_tele()
  1603. {
  1604.     register int newlev;
  1605.     d_level newlevel;
  1606.  
  1607.     if((u.uhave.amulet || In_endgame(&u.uz))
  1608. #ifdef WIZARD
  1609.                         && !wizard
  1610. #endif
  1611.                             ) {
  1612.         You("feel very disoriented for a moment.");
  1613.         return;
  1614.     }
  1615.     if(Teleport_control
  1616. #ifdef WIZARD
  1617.        || wizard
  1618. #endif
  1619.         ) {
  1620.         char buf[BUFSZ];
  1621.  
  1622.         do {
  1623.         getlin("To what level do you want to teleport? [type a number]",
  1624.             buf);
  1625.         if (!strcmp(buf,"\033"))    /* cancelled */
  1626.             return;
  1627.         } while(!digit(buf[0]) && (buf[0] != '-' || !digit(buf[1])));
  1628.         newlev = atoi(buf);
  1629.  
  1630.         /* no dungeon escape via this route */
  1631.         if(newlev == 0) {
  1632.             if(ynq("Go to Nowhere.  Are you sure?") != 'y') return;
  1633.             You("scream in agony as your body begins to warp...");
  1634.         display_nhwindow(WIN_MESSAGE, FALSE);
  1635.             You("cease to exist.");
  1636.             killer_format = NO_KILLER_PREFIX;
  1637.             killer = "committed suicide";
  1638.             done(DIED);
  1639.         return;  
  1640.         }
  1641. #ifdef MULDGN
  1642.         /* if in Knox and the requested level > 0, stay put.
  1643.          * we let negative values requests fall into the "heaven" loop.
  1644.          */
  1645.         if(Is_knox(&u.uz) && newlev > 0) {
  1646.             You(shudder_for_moment);
  1647.         return;
  1648.         }
  1649.         /* if in Quest, the player sees "Home 1", etc., on the status
  1650.          * line, instead of the logical depth of the level.  controlled
  1651.          * level teleport request is likely to be relativized to the
  1652.          * status line, and consequently it should be incremented to 
  1653.          * the value of the logical depth of the target level.
  1654.          *
  1655.          * we let negative values requests fall into the "heaven" loop.
  1656.          */
  1657.         if(In_quest(&u.uz) && newlev > 0)
  1658.             newlev = newlev + dungeons[u.uz.dnum].depth_start - 1;
  1659. #endif
  1660.     } else { /* involuntary level tele */
  1661. #ifdef MULDGN
  1662.         if(Is_knox(&u.uz)) {
  1663.             You(shudder_for_moment);
  1664.         return;
  1665.         }
  1666. #endif
  1667.         if(rn2(5)) newlev = rnd((int)depth(&u.uz) + 3);
  1668.         else {
  1669.         You(shudder_for_moment);
  1670.         return; 
  1671.         }
  1672.         if(newlev == depth(&u.uz)) {
  1673.         /* if in a single-level dungeon... */
  1674.         if(dunlevs_in_dungeon(&u.uz) == 1) {
  1675.             You(shudder_for_moment);
  1676.             return; 
  1677.         }
  1678.         else if(dunlev(&u.uz) == 1) newlev++;
  1679.         else if(dunlev(&u.uz) == dunlevs_in_dungeon(&u.uz)) newlev--;
  1680.             else if(In_hell(&u.uz)) newlev--;
  1681.         else newlev++;
  1682.         } 
  1683.     }
  1684.  
  1685. #ifdef WALKIES
  1686.     if(!next_to_u()) {
  1687.         You(shudder_for_moment);
  1688.         return;
  1689.     }
  1690. #endif
  1691.     if(newlev < 0) {
  1692.         if(newlev <= -10) {
  1693.             You("arrive in heaven.");
  1694.             verbalize("Thou art early, but we'll admit thee.");
  1695.             killer_format = NO_KILLER_PREFIX;
  1696.             killer = "went to heaven prematurely";
  1697.             done(DIED);
  1698.             return;
  1699.         } else    if (newlev == -9) {
  1700.             You("feel deliriously happy. ");
  1701.             pline("(In fact, you're on Cloud 9!) ");
  1702.             display_nhwindow(WIN_MESSAGE, FALSE);
  1703.         } else
  1704.             You("are now high above the clouds...");
  1705.  
  1706.         if(Levitation
  1707. #ifdef POLYSELF
  1708.            || is_floater(uasmon)
  1709. #endif
  1710.            ) {
  1711.             You("float gently down to earth.");
  1712.             u.uz.dnum = 0; /* he might have been in another dgn */
  1713.             newlev = 1;
  1714.         }
  1715. #ifdef POLYSELF
  1716.         else if(is_flyer(uasmon)) {
  1717.             You("fly down to earth.");
  1718.             u.uz.dnum = 0; /* he might have been in another dgn */
  1719.             newlev = 1;
  1720.         }
  1721. #endif
  1722.         else {
  1723.             d_level save_dlevel;
  1724.             
  1725.             assign_level(&save_dlevel, &u.uz);
  1726.             pline("Unfortunately, you don't know how to fly.");
  1727.             You("plummet a few thousand feet to your death.");
  1728.             u.uz.dnum = 0;
  1729.             u.uz.dlevel = 0;
  1730.             killer_format = NO_KILLER_PREFIX;
  1731.             killer =
  1732.     self_pronoun("teleported out of the dungeon and fell to %s death","his");
  1733.             done(DIED);
  1734.             assign_level(&u.uz, &save_dlevel);
  1735.             flags.botl = 1;
  1736.             return;
  1737.         }
  1738.     }
  1739.  
  1740. # ifdef WIZARD
  1741.     if (In_endgame(&u.uz)) {    /* must already be wizard */
  1742.         newlevel.dnum = u.uz.dnum;
  1743.         newlevel.dlevel = newlev;
  1744.         goto_level(&newlevel, FALSE, FALSE, FALSE);
  1745.         return;
  1746.     }
  1747. # endif
  1748.  
  1749.     /* calls done(ESCAPED) if newlevel==0 */
  1750.     if(u.uz.dnum == medusa_level.dnum &&
  1751.         newlev >= dungeons[u.uz.dnum].depth_start +
  1752.                         dunlevs_in_dungeon(&u.uz)) {
  1753.  
  1754.         goto_hell(TRUE, FALSE);
  1755.     } else {
  1756.         /* if invocation did not yet occur, teleporting into
  1757.          * the last level of Gehennom is forbidden.
  1758.          */
  1759.         if(Inhell && !u.uevent.invoked &&
  1760.             newlev >= (dungeons[u.uz.dnum].depth_start +
  1761.                     dunlevs_in_dungeon(&u.uz) - 1)) {
  1762.         newlev = dungeons[u.uz.dnum].depth_start +
  1763.                     dunlevs_in_dungeon(&u.uz) - 2;
  1764.         pline("Sorry...");
  1765.         }
  1766. #ifdef MULDGN
  1767.         /* no teleporting out of quest dungeon */
  1768.         if(In_quest(&u.uz) && newlev < depth(&qstart_level))
  1769.         newlev = depth(&qstart_level);
  1770. #endif
  1771.         /* the player thinks of levels purely in logical terms, so
  1772.          * we must translate newlev to a number relative to the
  1773.          * current dungeon.
  1774.            */
  1775.         get_level(&newlevel, newlev);
  1776.         goto_level(&newlevel, FALSE, FALSE, FALSE);
  1777.     }
  1778. }
  1779.  
  1780. static void
  1781. dofiretrap()
  1782. {
  1783.  
  1784.     register int num;
  1785.  
  1786.     /* changed to be in conformance with
  1787.      * SCR_FIRE by GAN 11/02/86
  1788.      */
  1789.  
  1790.     pline("A tower of flame bursts from the %s!", surface(u.ux,u.uy));
  1791.     if(Fire_resistance) {
  1792.         shieldeff(u.ux, u.uy);
  1793.         You("are uninjured.");
  1794.     } else {
  1795.         num = rnd(6);
  1796.         u.uhpmax -= num;
  1797.         losehp(num,"burst of flame", KILLED_BY_AN);
  1798.     }
  1799.     destroy_item(SCROLL_CLASS, AD_FIRE);
  1800.     destroy_item(SPBOOK_CLASS, AD_FIRE);
  1801.     destroy_item(POTION_CLASS, AD_FIRE);
  1802.     if (is_ice(u.ux, u.uy))
  1803.         melt_ice(u.ux, u.uy);
  1804. }
  1805.  
  1806. static void
  1807. domagicportal(ttmp)
  1808. register struct trap *ttmp;
  1809. {
  1810.     struct d_level target_level;
  1811.  
  1812.     /* if landed from another portal, do nothing */
  1813.     /* problem: level teleport landing escapes the check */
  1814.     if(!on_level(&u.uz, &u.uz0)) return;
  1815.  
  1816.     You("activated a magic portal!");
  1817.     You("feel dizzy for a moment, but the sensation passes.");
  1818.  
  1819.     /* prevent the poor shnook, whose amulet was stolen  */
  1820.     /* while in the endgame, from accidently triggering  */
  1821.     /* the portal to the next level, and thus losing the */
  1822.     /* game                                              */
  1823.     if(In_endgame(&u.uz) && !u.uhave.amulet) return;
  1824.  
  1825.     target_level = ttmp->dst;
  1826.     goto_level(&target_level, FALSE, FALSE, TRUE);
  1827. }
  1828.  
  1829. static void
  1830. domagictrap()
  1831. {
  1832.     register int fate = rnd(20);
  1833.  
  1834.     /* What happened to the poor sucker? */
  1835.  
  1836.     if (fate < 10) {
  1837.  
  1838.       /* Most of the time, it creates some monsters. */
  1839.       register int cnt = rnd(4);
  1840.  
  1841.       /* below checks for blindness added by GAN 10/30/86 */
  1842.       if (!Blind)  {
  1843.         You("are momentarily blinded by a flash of light!");
  1844.         make_blinded((long)rn1(5,10),FALSE);
  1845.       }  else
  1846.         You("hear a deafening roar!");
  1847.       while(cnt--)
  1848.         (void) makemon((struct permonst *) 0, u.ux, u.uy);
  1849.     }
  1850.     else
  1851.       switch (fate) {
  1852.  
  1853.          case 10:
  1854.          case 11:
  1855.               /* sometimes nothing happens */
  1856.             break;
  1857.          case 12: /* a flash of fire */
  1858.                 dofiretrap();
  1859.             break;
  1860.  
  1861.          /* odd feelings */
  1862.          case 13:    pline("A shiver runs up and down your %s!",
  1863.                   body_part(SPINE));
  1864.             break;
  1865.          case 14:    You(Hallucination ?
  1866.                 "hear the moon howling at you." :
  1867.                 "hear distant howling.");
  1868.             break;
  1869.          case 15:    You("suddenly yearn for %s.",
  1870.                 Hallucination ? "Cleveland" :
  1871.                         "your distant homeland");
  1872.             break;
  1873.          case 16:   Your("pack shakes violently!");
  1874.             break;
  1875.          case 17:    You(Hallucination ?
  1876.                 "smell hamburgers." :
  1877.                 "smell charred flesh.");
  1878.             break;
  1879.  
  1880.          /* very occasionally something nice happens. */
  1881.  
  1882.          case 19:
  1883.             /* tame nearby monsters */
  1884.            {   register int i,j;
  1885.                register struct monst *mtmp;
  1886.  
  1887.                /* below pline added by GAN 10/30/86 */
  1888.                (void) adjattrib(A_CHA,1,FALSE);
  1889.                for(i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) {
  1890.                if(!isok(u.ux+i, u.uy+j)) continue;
  1891.                mtmp = m_at(u.ux+i, u.uy+j);
  1892.                if(mtmp)
  1893.                    (void) tamedog(mtmp, (struct obj *)0);
  1894.                }
  1895.                break;
  1896.            }
  1897.  
  1898.          case 20:
  1899.             /* uncurse stuff */
  1900.            {  register struct obj *obj;
  1901.  
  1902.             /* below plines added by GAN 10/30/86 */
  1903.             You(Hallucination ?
  1904.                 "feel in touch with the Universal Oneness." :
  1905.                 "feel like someone is helping you.");
  1906.             for(obj = invent; obj ; obj = obj->nobj)
  1907.                    if(obj->owornmask || obj->otyp == LOADSTONE)
  1908.                     uncurse(obj);
  1909.                if(Punished) unpunish();
  1910.                break;
  1911.            }
  1912.          default: break;
  1913.       }
  1914. }
  1915.  
  1916. void
  1917. water_damage(obj, force, here)
  1918. register struct obj *obj;
  1919. register boolean force, here;
  1920. {
  1921.     /* Scrolls, spellbooks, potions, weapons and
  1922.        pieces of armor may get affected by the water */
  1923.     for (; obj; obj = (here ? obj->nexthere : obj->nobj)) {
  1924.  
  1925.         (void) snuff_lit(obj);
  1926.  
  1927.         if(obj->greased) {
  1928.             if (force || !rn2(2)) obj->greased = 0;
  1929.         } else if(Is_container(obj) && !Is_box(obj) &&
  1930.             (obj->otyp != OILSKIN_SACK || (obj->cursed && !rn2(3)))) {
  1931.             water_damage(obj->cobj, force, FALSE);
  1932.         } else if(obj->oclass == SCROLL_CLASS && (force || rn2(12) > Luck)
  1933. #ifdef MAIL
  1934.               && obj->otyp != SCR_MAIL
  1935. #endif
  1936.               ) {
  1937.             obj->otyp = SCR_BLANK_PAPER;
  1938.         } else if(obj->oclass == SPBOOK_CLASS && (force || rn2(12) > Luck)) {
  1939.             if (obj->otyp == SPE_BOOK_OF_THE_DEAD)
  1940.                 pline("Steam rises from %s.", the(xname(obj)));
  1941.             else obj->otyp = SPE_BLANK_PAPER;
  1942.         } else if(obj->oclass == POTION_CLASS && (force || rn2(12) > Luck)) {
  1943.             if (obj->spe == -1) {
  1944.                 obj->otyp = POT_WATER;
  1945.                 obj->blessed = obj->cursed = 0;
  1946.                 obj->spe = 0;
  1947.             } else obj->spe--;
  1948.         } else if(is_rustprone(obj) && obj->oeroded < MAX_ERODE &&
  1949.               !(obj->oerodeproof || (obj->blessed && !rnl(4))) &&
  1950.               (force || rn2(12) > Luck)) {
  1951.             /* all metal stuff and armor except (body armor
  1952.                protected by oilskin cloak) */
  1953.             if(obj->oclass != ARMOR_CLASS || obj != uarm ||
  1954.                !uarmc || uarmc->otyp != OILSKIN_CLOAK ||
  1955.                 (uarmc->cursed && !rn2(3)))
  1956.                 obj->oeroded++;
  1957.         }
  1958.     }
  1959. }
  1960.  
  1961. /*
  1962.  * This function is potentially expensive - rolling
  1963.  * inventory list multiple times.  Luckily it's seldom needed.
  1964.  * Returns TRUE if disrobing made player unencumbered enough to
  1965.  * crawl out of the current predicament.
  1966.  */
  1967. static boolean
  1968. emergency_disrobe(lostsome)
  1969. boolean *lostsome;
  1970. {
  1971.     int invc = inv_cnt();
  1972.  
  1973.     while (near_capacity() > (Punished ? UNENCUMBERED : SLT_ENCUMBER)) {
  1974.         register struct obj *obj, *otmp = (struct obj *)0;
  1975.         register int i = rn2(invc);
  1976.  
  1977.         for (obj = invent; obj; obj = obj->nobj) {
  1978.             /*
  1979.              * Undroppables are: body armor, boots, gloves,
  1980.              * amulets, and rings because of the time and effort
  1981.              * in removing them + loadstone and other cursed stuff
  1982.              * for obvious reasons.
  1983.              */
  1984.             if (!(obj->otyp == LOADSTONE ||
  1985.                   obj == uamul || obj == uleft || obj == uright ||
  1986.                   obj == ublindf || obj == uarm || obj == uarmc ||
  1987.                   obj == uarmg || obj == uarmf ||
  1988. #ifdef TOURIST
  1989.                   obj == uarmu ||
  1990. #endif
  1991.                   (obj->cursed && (obj == uarmh || obj == uarms)) ||
  1992.                   welded(obj)))
  1993.                 otmp = obj;
  1994.             /* reached the mark and found some stuff to drop? */
  1995.             if (--i < 0 && otmp) break;
  1996.  
  1997.             /* else continue */
  1998.         }
  1999.  
  2000.         /* nothing to drop and still overweight */
  2001.         if (!otmp) return(FALSE);
  2002.  
  2003.         if (otmp == uarmh) (void) Helmet_off();
  2004.         else if (otmp == uarms) (void) Shield_off();
  2005.         else if (otmp == uwep) setuwep((struct obj *)0);
  2006.         *lostsome = TRUE;
  2007.         dropx(otmp);
  2008.         invc--;
  2009.     }
  2010.     return(TRUE);
  2011. }
  2012.  
  2013. /*
  2014.  *  return(TRUE) == player relocated
  2015.  */
  2016. boolean
  2017. drown()
  2018. {
  2019.     boolean inpool_ok = FALSE, crawl_ok;
  2020.     int i, x, y;
  2021.  
  2022.     /* happily wading in the same contiguous pool */
  2023.     if (u.uinwater && is_pool(u.ux-u.dx,u.uy-u.dy) &&
  2024.         (
  2025. #ifdef POLYSELF
  2026.          is_swimmer(uasmon) ||
  2027. #endif
  2028.          Amphibious)) {
  2029.         /* water effects on objects every now and then */
  2030.         if (!rn2(5)) inpool_ok = TRUE;
  2031.         else return(FALSE);
  2032.     }
  2033.  
  2034.     if (!u.uinwater) {
  2035.         You("%s into the water%c",
  2036.         Is_waterlevel(&u.uz) ? "plunge" : "fall",
  2037.         Amphibious ? '.' : '!');
  2038. #ifdef POLYSELF
  2039.         if(!is_swimmer(uasmon))
  2040. #endif
  2041.         if (!Is_waterlevel(&u.uz))
  2042.             You("sink like %s.",
  2043.             Hallucination ? "the Titanic" : "a rock");
  2044.     }
  2045.  
  2046.     water_damage(invent, FALSE, FALSE);
  2047.  
  2048. #ifdef POLYSELF
  2049.     if(u.umonnum == PM_GREMLIN && rn2(3)) {
  2050.         struct monst *mtmp;
  2051.         if ((mtmp = cloneu()) != 0) {
  2052.             mtmp->mhpmax = (u.mhmax /= 2);
  2053.             You("multiply.");
  2054.         }
  2055.     }
  2056. #endif
  2057.     if (inpool_ok) return(FALSE);
  2058. #ifdef WALKIES
  2059.     if ((i = number_leashed()) > 0) {
  2060.         pline("The leash%s slip%s loose.",
  2061.             (i > 1) ? "es" : "",
  2062.             (i > 1) ? "" : "s");
  2063.         unleash_all();
  2064.     }
  2065. #endif
  2066.     if (Amphibious
  2067. #ifdef POLYSELF
  2068.             || is_swimmer(uasmon)
  2069. #endif
  2070.                         ) {
  2071.         if (Amphibious) {
  2072.             if (flags.verbose)
  2073.                 pline("But you aren't drowning.");
  2074.             if (!Is_waterlevel(&u.uz))
  2075.                 if (Hallucination) 
  2076.                     Your("keel hits the bottom.");
  2077.                 else
  2078.                     You("touch bottom.");
  2079.         }
  2080.         if (Punished) {
  2081.             unplacebc();
  2082.             placebc();
  2083.         }
  2084.         u.uinwater = 1;
  2085.         under_water(1);
  2086.         vision_full_recalc = 1;
  2087.         return(FALSE);
  2088.     }
  2089.     if((Teleportation || can_teleport(uasmon)) &&
  2090.        (Teleport_control || rn2(3) < Luck+2)) {
  2091.         You("attempt a teleport spell.");    /* utcsri!carroll */
  2092.         (void) dotele();
  2093.         if(!is_pool(u.ux,u.uy))
  2094.             return(TRUE);
  2095.     }
  2096.     crawl_ok = FALSE;
  2097.     /* look around for a place to crawl to */
  2098.     for (i = 0; i < 100; i++) {
  2099.         x = rn1(3,u.ux - 1);
  2100.         y = rn1(3,u.uy - 1);
  2101.         if (teleok(x,y,TRUE)) {
  2102.             crawl_ok = TRUE;
  2103.             goto crawl;
  2104.         }
  2105.     }
  2106.     /* one more scan */
  2107.     for (x = u.ux - 1; x <= u.ux + 1; x++)
  2108.         for (y = u.uy - 1; y <= u.uy + 1; y++)
  2109.             if (teleok(x,y,TRUE)) {
  2110.                 crawl_ok = TRUE;
  2111.                 goto crawl;
  2112.             }
  2113. crawl:;
  2114.     if (crawl_ok) {
  2115.         boolean lost = FALSE;
  2116.         /* time to do some strip-tease... */
  2117.         boolean succ = Is_waterlevel(&u.uz) ? TRUE :
  2118.                 emergency_disrobe(&lost);
  2119.  
  2120.         You("try to crawl out of the water.");
  2121.         if (lost)
  2122.             You("dump some of your gear to lose weight...");
  2123.         if (succ) {
  2124.             pline("Pheew!  That was close.");
  2125.             teleds(x,y);
  2126.             return(TRUE);
  2127.         }
  2128.         /* still too much weight */
  2129.         pline("But in vain.");
  2130.     }
  2131.     u.uinwater = 1;
  2132.     You("drown.");
  2133.     killer_format = KILLED_BY_AN;
  2134.     killer = (levl[u.ux][u.uy].typ == POOL || Is_medusa_level(&u.uz)) ?
  2135.         "pool of water" : "moat";
  2136.     done(DROWNING);
  2137.     /* oops, we're still alive.  better get out of the water. */
  2138.     if (!safe_teleds())
  2139.         while (1) {
  2140.             pline("You're still drowning.");
  2141.             done(DROWNING);
  2142.         }
  2143.     u.uinwater = 0;
  2144.     You("find yourself back %s.", Is_waterlevel(&u.uz) ?
  2145.         "in an air bubble" : "on land");
  2146.     return(TRUE);
  2147. }
  2148.  
  2149. void
  2150. drain_en(n)
  2151. register int n;
  2152. {
  2153.     if (!u.uenmax) return;
  2154.     You("feel your magical energy drain away!");
  2155.     u.uen -= n;
  2156.     if(u.uen < 0)  {
  2157.         u.uenmax += u.uen;
  2158.         if(u.uenmax < 0) u.uenmax = 0;
  2159.         u.uen = 0;
  2160.     }
  2161.     flags.botl = 1;
  2162. }
  2163.  
  2164. int
  2165. dountrap()    /* disarm a trapped object */
  2166. {
  2167. #ifdef POLYSELF
  2168.     if(nohands(uasmon)) {
  2169.         pline("And just how do you expect to do that?");
  2170.         return(0);
  2171.     }
  2172. #endif
  2173.     return untrap(FALSE);
  2174. }
  2175.  
  2176. int
  2177. untrap(force)
  2178. boolean force;
  2179. {
  2180.     register struct obj *otmp;
  2181.     register boolean confused = (Confusion > 0 || Hallucination > 0);
  2182.     register int x,y;
  2183.     int ch;
  2184.     struct trap *ttmp;
  2185.     struct monst *mtmp;
  2186.     boolean trap_skipped = FALSE;
  2187.  
  2188.     if(!getdir(NULL)) return(0);
  2189.     x = u.ux + u.dx;
  2190.     y = u.uy + u.dy;
  2191.  
  2192.     if(!u.dx && !u.dy) {
  2193.         for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
  2194.         if(Is_box(otmp)) {
  2195.             pline("There is %s here.", doname(otmp));
  2196.  
  2197.             switch (ynq("Check for traps?")) {
  2198.             case 'q': return(0);
  2199.             case 'n': continue;
  2200.             }
  2201.  
  2202.             if((otmp->otrapped && (force || (!confused
  2203.                 && rn2(MAXULEV + 1 - (int)u.ulevel) < 10)))
  2204.                || (!force && confused && !rn2(3))) {
  2205.             You("find a trap on %s!", the(xname(otmp)));
  2206.             exercise(A_WIS, TRUE);
  2207.  
  2208.             switch (ynq("Disarm it?")) {
  2209.                 case 'q': return(1);
  2210.                 case 'n': trap_skipped = TRUE;  continue;
  2211.             }
  2212.  
  2213.             if(otmp->otrapped) {
  2214.                 exercise(A_DEX, TRUE);
  2215.                 ch = ACURR(A_DEX) + u.ulevel;
  2216.                 if (pl_character[0] == 'R') ch *= 2;
  2217.                 if(!force && (confused || Fumbling ||
  2218.                 rnd(75+level_difficulty()/2) > ch)) {
  2219.                 (void) chest_trap(otmp, FINGER, TRUE);
  2220.                 } else {
  2221.                 You("disarm it!");
  2222.                 otmp->otrapped = 0;
  2223.                 }
  2224.             } else pline("That %s was not trapped.", doname(otmp));
  2225.             return(1);
  2226.             } else {
  2227.             You("find no traps on %s.", the(xname(otmp)));
  2228.             return(1);
  2229.             }
  2230.         }
  2231.         if ((ttmp = t_at(x,y)) && ttmp->tseen)
  2232.         You("cannot disable this trap.");
  2233.         else
  2234.         You(trap_skipped ? "find no other traps here."
  2235.                  : "know of no traps here.");
  2236.         return(0);
  2237.     }
  2238.  
  2239.     if ((mtmp = m_at(x,y))                &&
  2240.         mtmp->m_ap_type == M_AP_FURNITURE    &&
  2241.         (mtmp->mappearance == S_hcdoor ||
  2242.             mtmp->mappearance == S_vcdoor)    &&
  2243.         !Protection_from_shape_changers)     {
  2244.  
  2245.         stumble_onto_mimic(mtmp);
  2246.         return(1);
  2247.     }
  2248.  
  2249.     if (!IS_DOOR(levl[x][y].typ)) {
  2250.         if ((ttmp = t_at(x,y)) && ttmp->tseen)
  2251.         You("cannot disable that trap.");
  2252.         else
  2253.         You("know of no traps there.");
  2254.         return(0);
  2255.     }
  2256.  
  2257.     switch (levl[x][y].doormask) {
  2258.         case D_NODOOR:
  2259.         You("%s no door there.", Blind ? "feel" : "see");
  2260.         return(0);
  2261.         case D_ISOPEN:
  2262.         pline("This door is safely open.");
  2263.         return(0);
  2264.         case D_BROKEN:
  2265.         pline("This door is broken.");
  2266.         return(0);
  2267.     }
  2268.  
  2269.     if ((levl[x][y].doormask & D_TRAPPED
  2270.          && (force ||
  2271.          (!confused && rn2(MAXULEV - (int)u.ulevel + 11) < 10)))
  2272.         || (!force && confused && !rn2(3))) {
  2273.         You("find a trap on the door!");
  2274.         exercise(A_WIS, TRUE);
  2275.         if (ynq("Disarm it?") != 'y') return(1);
  2276.         if (levl[x][y].doormask & D_TRAPPED) {
  2277.             ch = 15 +
  2278.              (pl_character[0] == 'R') ? u.ulevel*3 :
  2279.              u.ulevel;
  2280.             exercise(A_DEX, TRUE);
  2281.             if(!force && (confused || Fumbling || 
  2282.                              rnd(75+level_difficulty()/2) > ch)) {
  2283.                 You("set it off!");
  2284.                 b_trapped("door", FINGER);
  2285.             } else
  2286.                 You("disarm it!");
  2287.             levl[x][y].doormask &= ~D_TRAPPED;
  2288.         } else pline("This door was not trapped.");
  2289.         return(1);
  2290.     } else {
  2291.         You("find no traps on the door.");
  2292.         return(1);
  2293.     }
  2294. }
  2295.  
  2296. /* only called when the player is doing something to the chest directly */
  2297. boolean
  2298. chest_trap(obj, bodypart, disarm)
  2299. register struct obj *obj;
  2300. register int bodypart;
  2301. boolean disarm;
  2302. {
  2303.     register struct obj *otmp = obj, *otmp2;
  2304.     char    buf[80];
  2305.     const char *msg;
  2306.  
  2307.     You(disarm ? "set it off!" : "trigger a trap!");
  2308.     display_nhwindow(WIN_MESSAGE, FALSE);
  2309.     if (Luck > -13 && rn2(13+Luck) > 7) {    /* saved by luck */
  2310.         /* trap went off, but good luck prevents damage */
  2311.         switch (rn2(13)) {
  2312.         case 12:
  2313.         case 11:  msg = "explosive charge is a dud";  break;
  2314.         case 10:
  2315.         case  9:  msg = "electric charge is grounded";  break;
  2316.         case  8:
  2317.         case  7:  msg = "flame fizzles out";  break;
  2318.         case  6:
  2319.         case  5:
  2320.         case  4:  msg = "poisoned needle misses";  break;
  2321.         case  3:
  2322.         case  2:
  2323.         case  1:
  2324.         case  0:  msg = "gas cloud blows away";  break;
  2325.         default:  impossible("chest disarm bug");  msg = NULL;  break;
  2326.         }
  2327.         if (msg) pline("But luckily the %s!", msg);
  2328.     } else {
  2329.         switch(rn2(20) ? ((Luck >= 13) ? 0 : rn2(13-Luck)) : rn2(26)) {
  2330.         case 25:
  2331.         case 24:
  2332.         case 23:
  2333.         case 22:
  2334.         case 21: {
  2335.                   register struct monst *shkp;
  2336.               long loss = 0L;
  2337.               boolean costly, insider;
  2338.               register xchar ox = obj->ox, oy = obj->oy;
  2339.  
  2340. #ifdef GCC_WARN
  2341.               shkp = (struct monst *) 0;
  2342. #endif
  2343.               /* the obj location need not be that of player */
  2344.               costly = (costly_spot(ox, oy) && 
  2345.                    (shkp = shop_keeper(*in_rooms(ox, oy,
  2346.                     SHOPBASE))) != (struct monst *)0);
  2347.               insider = (*u.ushops && inside_shop(u.ux, u.uy) &&
  2348.                     *in_rooms(ox, oy, SHOPBASE) == *u.ushops);
  2349.  
  2350.               pline("%s explodes!", The(xname(obj)));
  2351.               Sprintf(buf, "exploding %s", xname(obj));
  2352.  
  2353.               if(costly)
  2354.                   loss += stolen_value(obj, ox, oy,
  2355.                         (boolean)shkp->mpeaceful, TRUE);
  2356.               delete_contents(obj);
  2357.               for(otmp = level.objects[u.ux][u.uy];
  2358.                             otmp; otmp = otmp2) {
  2359.                   otmp2 = otmp->nexthere;
  2360.                   if(costly)
  2361.                       loss += stolen_value(otmp, otmp->ox, 
  2362.                       otmp->oy, (boolean)shkp->mpeaceful,
  2363.                       TRUE);
  2364.                   delobj(otmp);
  2365.               }
  2366.               exercise(A_STR, FALSE);
  2367.               losehp(d(6,6), buf, KILLED_BY_AN);
  2368.               if(costly && loss) {
  2369.                   if(insider)
  2370.                   You("owe %ld zorkmids for objects destroyed.",
  2371.                                               loss);
  2372.                   else {
  2373.                             You("caused %ld zorkmids worth of damage!",
  2374.                                                   loss);
  2375.                       make_angry_shk(shkp, ox, oy);
  2376.                   }
  2377.               }
  2378.               wake_nearby();
  2379.               return TRUE;
  2380.             }
  2381.         case 20:
  2382.         case 19:
  2383.         case 18:
  2384.         case 17:
  2385.             pline("A cloud of noxious gas billows from %s.",
  2386.                   the(xname(obj)));
  2387.             poisoned("gas cloud", A_STR, "cloud of poison gas",15);
  2388.             exercise(A_CON, FALSE);
  2389.             break;
  2390.         case 16:
  2391.         case 15:
  2392.         case 14:
  2393.         case 13:
  2394.             You("feel a needle prick your %s.",body_part(bodypart));
  2395.             poisoned("needle", A_CON, "poisoned needle",10);
  2396.             exercise(A_CON, FALSE);
  2397.             break;
  2398.         case 12:
  2399.         case 11:
  2400.         case 10:
  2401.         case 9:
  2402.             pline("A tower of flame erupts from %s!",
  2403.                   the(xname(obj)));
  2404.             if(Fire_resistance) {
  2405.                 shieldeff(u.ux, u.uy);
  2406.                 You("don't seem to be affected.");
  2407.             } else    losehp(d(4, 6), "tower of flame", KILLED_BY_AN);
  2408.             destroy_item(SCROLL_CLASS, AD_FIRE);
  2409.             destroy_item(SPBOOK_CLASS, AD_FIRE);
  2410.             destroy_item(POTION_CLASS, AD_FIRE);
  2411.             if (is_ice(u.ux, u.uy))
  2412.                 melt_ice(u.ux, u.uy);
  2413.             break;
  2414.         case 8:
  2415.         case 7:
  2416.         case 6:
  2417.             You("are jolted by a surge of electricity!");
  2418.             if(Shock_resistance)  {
  2419.                 shieldeff(u.ux, u.uy);
  2420.                 You("don't seem to be affected.");
  2421.             } else    losehp(d(4, 4), "electric shock", KILLED_BY_AN);
  2422.             destroy_item(RING_CLASS, AD_ELEC);
  2423.             destroy_item(WAND_CLASS, AD_ELEC);
  2424.             break;
  2425.         case 5:
  2426.         case 4:
  2427.         case 3:
  2428.             pline("Suddenly you are frozen in place!");
  2429.             nomul(-d(5, 6));
  2430.             exercise(A_DEX, FALSE);
  2431.             nomovemsg = "You can move again.";
  2432.             break;
  2433.         case 2:
  2434.         case 1:
  2435.         case 0:
  2436.             pline("A cloud of %s gas billows from %s.",
  2437.                   hcolor(), the(xname(obj)));
  2438.             if(!Stunned) {
  2439.                 if (Hallucination)
  2440.                 pline("What a groovy feeling!");
  2441.                 else if (Blind)
  2442.                 You("stagger and get dizzy...");
  2443.                 else
  2444.                 You("stagger and your vision blurs...");
  2445.             }
  2446.             make_stunned(HStun + rn1(7, 16),FALSE);
  2447.             make_hallucinated(HHallucination + rn1(5, 16),FALSE,0L);
  2448.             break;
  2449.         default: impossible("bad chest trap");
  2450.             break;
  2451.         }
  2452.         bot();            /* to get immediate botl re-display */
  2453.     }
  2454.     otmp->otrapped = 0;        /* these traps are one-shot things */
  2455.  
  2456.     return FALSE;
  2457. }
  2458.  
  2459. #endif /* OVLB */
  2460. #ifdef OVL0
  2461.  
  2462. struct trap *
  2463. t_at(x,y)
  2464. register int x, y;
  2465. {
  2466.     register struct trap *trap = ftrap;
  2467.     while(trap) {
  2468.         if(trap->tx == x && trap->ty == y) return(trap);
  2469.         trap = trap->ntrap;
  2470.     }
  2471.     return((struct trap *)0);
  2472. }
  2473.  
  2474. #endif /* OVL0 */
  2475. #ifdef OVLB
  2476.  
  2477. void
  2478. deltrap(trap)
  2479. register struct trap *trap;
  2480. {
  2481.     register struct trap *ttmp;
  2482.  
  2483.     if(trap == ftrap)
  2484.         ftrap = ftrap->ntrap;
  2485.     else {
  2486.         for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ;
  2487.         ttmp->ntrap = trap->ntrap;
  2488.     }
  2489.     dealloc_trap(trap);
  2490. }
  2491.  
  2492. /* used for doors (also tins).  can be used for anything else that opens. */
  2493. void
  2494. b_trapped(item, bodypart)
  2495. register const char *item;
  2496. register int bodypart;
  2497. {
  2498.     register int lvl = level_difficulty();
  2499.     int dmg = rnd(5 + (lvl < 5 ? lvl : 2+lvl/2));
  2500.  
  2501.     pline("KABOOM!!  %s was booby-trapped!", The(item));
  2502.     losehp(dmg, "explosion", KILLED_BY_AN);
  2503.     exercise(A_STR, FALSE);
  2504.     if (bodypart) exercise(A_CON, FALSE);
  2505.     make_stunned(HStun + dmg, TRUE);
  2506. }
  2507.  
  2508. /* Monster is hit by trap. */
  2509. /* Note: doesn't work if both obj and d_override are null */
  2510. STATIC_OVL boolean
  2511. thitm(tlev, mon, obj, d_override)
  2512. register int tlev;
  2513. register struct monst *mon;
  2514. register struct obj *obj;
  2515. int d_override;
  2516. {
  2517.     register int strike;
  2518.     register boolean trapkilled = FALSE;
  2519.  
  2520.     if (d_override) strike = 1;
  2521.     else if (obj) strike = (find_mac(mon) + tlev + obj->spe <= rnd(20));
  2522.     else strike = (find_mac(mon) + tlev <= rnd(20));
  2523.  
  2524.     /* Actually more accurate than thitu, which doesn't take
  2525.      * obj->spe into account.
  2526.      */
  2527.     if(!strike) {
  2528.         if (cansee(mon->mx, mon->my))
  2529.             pline("%s is almost hit by %s!", Monnam(mon),
  2530.                                 doname(obj));
  2531.     } else {
  2532.         int dam = 1;
  2533.  
  2534.         if (obj && cansee(mon->mx, mon->my))
  2535.             pline("%s is hit by %s!", Monnam(mon), doname(obj));
  2536.         if (d_override) dam = d_override;
  2537.         else if (obj) {
  2538.             dam = dmgval(obj, mon->data);
  2539.             if (dam < 1) dam = 1;
  2540.         }
  2541.         if ((mon->mhp -= dam) <= 0) {
  2542.             int xx = mon->mx;
  2543.             int yy = mon->my;
  2544.  
  2545.             monkilled(mon, "", AD_PHYS);
  2546. #ifdef MUSE
  2547.             if (mon->mhp <= 0) {
  2548. #endif
  2549.                 newsym(xx, yy);
  2550.                 trapkilled = TRUE;
  2551. #ifdef MUSE
  2552.             }
  2553. #endif
  2554.         }
  2555.     }
  2556.     if (obj && (!strike || d_override)) {
  2557.         place_object(obj, mon->mx, mon->my);
  2558.         obj->nobj = fobj;
  2559.         fobj = obj;
  2560.         stackobj(fobj);
  2561.     } else if (obj) dealloc_obj(obj);
  2562.  
  2563.     return trapkilled;
  2564. }
  2565.  
  2566. boolean
  2567. unconscious()
  2568. {
  2569.     return((boolean)(multi < 0 && (!nomovemsg ||
  2570.         u.usleep ||
  2571.         !strncmp(nomovemsg,"You regain con", 15) ||
  2572.         !strncmp(nomovemsg,"You are consci", 15))));
  2573. }
  2574.  
  2575. static char lava_killer[] = "molten lava";
  2576.  
  2577. boolean
  2578. lava_effects()
  2579. {
  2580.     register struct obj *obj, *obj2;
  2581.     int dmg;
  2582.  
  2583.     if (!Fire_resistance) {
  2584.     if(Wwalking) {
  2585.         dmg = d(6,6);
  2586.         pline("The lava here burns you!");
  2587.         if(dmg < u.uhp) {
  2588.         losehp(dmg, lava_killer, KILLED_BY);
  2589.         goto burn_stuff;
  2590.         }
  2591.     } else
  2592.         You("fall into the lava!");
  2593.  
  2594.     for(obj = invent; obj; obj = obj2) {
  2595.         obj2 = obj->nobj;
  2596.         if(is_organic(obj) && !obj->oerodeproof) {
  2597.         if(obj->owornmask) {
  2598.             if(obj == uarm) (void) Armor_gone();
  2599.             else if(obj == uarmc) (void) Cloak_off();
  2600.             else if(obj == uarmh) (void) Helmet_off();
  2601.             else if(obj == uarms) (void) Shield_off();
  2602.             else if(obj == uarmg) (void) Gloves_off();
  2603.             else if(obj == uarmf) (void) Boots_off();
  2604. #ifdef TOURIST
  2605.             else if(obj == uarmu) setnotworn(obj);
  2606. #endif
  2607.             else if(obj == uleft) Ring_gone(obj);
  2608.             else if(obj == uright) Ring_gone(obj);
  2609.             else if(obj == ublindf) Blindf_off(obj);
  2610.             else if(obj == uwep) uwepgone();
  2611.             if(Lifesaved
  2612. #ifdef WIZARD
  2613.                || wizard
  2614. #endif
  2615.                ) Your("%s into flame!", aobjnam(obj, "burst"));
  2616.         }
  2617.         useup(obj);
  2618.         }
  2619.     }
  2620.  
  2621.     /* s/he died... */
  2622.     u.uhp = -1;
  2623.     killer_format = KILLED_BY;
  2624.     killer = lava_killer;
  2625.     You("burn to a crisp...");
  2626.     done(BURNING);
  2627.     if (!safe_teleds())
  2628.         while (1) {
  2629.             pline("You're still burning.");
  2630.             done(BURNING);
  2631.         }
  2632.     You("find yourself back on solid %s.", surface(u.ux, u.uy));
  2633.     return(TRUE);
  2634.     }
  2635.  
  2636.     if (!Wwalking) {
  2637.     u.utrap = rn1(4, 4) + (rn1(4, 12) << 8);
  2638.     u.utraptype = TT_LAVA;
  2639.     You("sink into the lava, but it doesn't burn you!");
  2640.     }
  2641.     /* just want to burn boots, not all armor; destroy_item doesn't work on
  2642.        armor anyway */
  2643. burn_stuff:
  2644.     if(uarmf && !uarmf->oerodeproof && is_organic(uarmf)) {
  2645.     /* save uarmf value because Boots_off() sets uarmf to NULL */
  2646.     obj = uarmf;
  2647.     Your("%s burst into flame!", xname(obj));
  2648.     (void) Boots_off();
  2649.     useup(obj);
  2650.     }
  2651.     destroy_item(SCROLL_CLASS, AD_FIRE);
  2652.     destroy_item(SPBOOK_CLASS, AD_FIRE);
  2653.     destroy_item(POTION_CLASS, AD_FIRE);
  2654.     return(FALSE);
  2655. }
  2656.  
  2657. #endif /* OVLB */
  2658.  
  2659. /*trap.c*/
  2660.